[runtime] Replace mono_class_from_name with mono_class_load_from_name for explicit...
[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)
7840 {
7841         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7842         MonoImage *file_image;
7843         MonoClass *klass;
7844         int i;
7845
7846         /* 
7847          * The EXPORTEDTYPES table only contains public types, so have to search the
7848          * modules as well.
7849          * Note: image->modules contains the contents of the MODULEREF table, while
7850          * the real module list is in the FILE table.
7851          */
7852         for (i = 0; i < file_table->rows; i++) {
7853                 guint32 cols [MONO_FILE_SIZE];
7854                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7855                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7856                         continue;
7857
7858                 file_image = mono_image_load_file_for_image (image, i + 1);
7859                 if (file_image) {
7860                         klass = mono_class_from_name (file_image, name_space, name);
7861                         if (klass)
7862                                 return klass;
7863                 }
7864         }
7865
7866         return NULL;
7867 }
7868
7869 static MonoClass *
7870 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, MonoError *error, GHashTable* visited_images)
7871 {
7872         GHashTable *nspace_table;
7873         MonoImage *loaded_image;
7874         guint32 token = 0;
7875         int i;
7876         MonoClass *klass;
7877         char *nested;
7878         char buf [1024];
7879
7880         mono_error_init (error);
7881
7882         // Checking visited images avoids stack overflows when cyclic references exist.
7883         if (g_hash_table_lookup (visited_images, image))
7884                 return NULL;
7885
7886         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7887
7888         if ((nested = strchr (name, '/'))) {
7889                 int pos = nested - name;
7890                 int len = strlen (name);
7891                 if (len > 1023)
7892                         return NULL;
7893                 memcpy (buf, name, len + 1);
7894                 buf [pos] = 0;
7895                 nested = buf + pos + 1;
7896                 name = buf;
7897         }
7898
7899         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7900         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7901                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7902                 if (res) {
7903                         if (!klass)
7904                                 klass = search_modules (image, name_space, name);
7905                         if (nested)
7906                                 return klass ? return_nested_in (klass, nested) : NULL;
7907                         else
7908                                 return klass;
7909                 }
7910         }
7911
7912         mono_image_init_name_cache (image);
7913         mono_image_lock (image);
7914
7915         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7916
7917         if (nspace_table)
7918                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7919
7920         mono_image_unlock (image);
7921
7922         if (!token && image_is_dynamic (image) && image->modules) {
7923                 /* Search modules as well */
7924                 for (i = 0; i < image->module_count; ++i) {
7925                         MonoImage *module = image->modules [i];
7926
7927                         klass = mono_class_from_name (module, name_space, name);
7928                         if (klass)
7929                                 return klass;
7930                 }
7931         }
7932
7933         if (!token) {
7934                 klass = search_modules (image, name_space, name);
7935                 if (klass)
7936                         return klass;
7937         }
7938
7939         if (!token)
7940                 return NULL;
7941
7942         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7943                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7944                 guint32 cols [MONO_EXP_TYPE_SIZE];
7945                 guint32 idx, impl;
7946
7947                 idx = mono_metadata_token_index (token);
7948
7949                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7950
7951                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7952                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7953                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7954                         if (!loaded_image)
7955                                 return NULL;
7956                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, error, visited_images);
7957                         if (nested)
7958                                 return klass ? return_nested_in (klass, nested) : NULL;
7959                         return klass;
7960                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7961                         guint32 assembly_idx;
7962
7963                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7964
7965                         mono_assembly_load_reference (image, assembly_idx - 1);
7966                         g_assert (image->references [assembly_idx - 1]);
7967                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7968                                 return NULL;                    
7969                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, error, visited_images);
7970                         if (nested)
7971                                 return return_nested_in (klass, nested);
7972                         return klass;
7973                 } else {
7974                         g_assert_not_reached ();
7975                 }
7976         }
7977
7978         token = MONO_TOKEN_TYPE_DEF | token;
7979
7980         klass = mono_class_get_checked (image, token, error);
7981         if (nested)
7982                 return return_nested_in (klass, nested);
7983         return klass;
7984 }
7985
7986 /**
7987  * mono_class_from_name_checked:
7988  * @image: The MonoImage where the type is looked up in
7989  * @name_space: the type namespace
7990  * @name: the type short name.
7991  *
7992  * Obtains a MonoClass with a given namespace and a given name which
7993  * is located in the given MonoImage.
7994  *
7995  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7996  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7997  */
7998 MonoClass *
7999 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
8000 {
8001         MonoClass *klass;
8002         GHashTable *visited_images;
8003
8004         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
8005
8006         klass = mono_class_from_name_checked_aux (image, name_space, name, error, visited_images);
8007
8008         g_hash_table_destroy (visited_images);
8009
8010         return klass;
8011 }
8012
8013 /**
8014  * mono_class_from_name:
8015  * @image: The MonoImage where the type is looked up in
8016  * @name_space: the type namespace
8017  * @name: the type short name.
8018  *
8019  * Obtains a MonoClass with a given namespace and a given name which
8020  * is located in the given MonoImage.
8021  *
8022  * To reference nested classes, use the "/" character as a separator.
8023  * For example use "Foo/Bar" to reference the class Bar that is nested
8024  * inside Foo, like this: "class Foo { class Bar {} }".
8025  */
8026 MonoClass *
8027 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8028 {
8029         MonoError error;
8030         MonoClass *klass;
8031
8032         klass = mono_class_from_name_checked (image, name_space, name, &error);
8033         if (!mono_error_ok (&error)) {
8034                 mono_loader_set_error_from_mono_error (&error);
8035                 mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8036         }
8037         return klass;
8038 }
8039
8040 /**
8041  * mono_class_load_from_name:
8042  * @image: The MonoImage where the type is looked up in
8043  * @name_space: the type namespace
8044  * @name: the type short name.
8045  *
8046  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8047  * This function should be used by the runtime for critical types to which there's no way to recover but crash
8048  * If they are missing. Thing of System.Object or System.String.
8049  */
8050 MonoClass *
8051 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8052 {
8053         MonoError error;
8054         MonoClass *klass;
8055
8056         klass = mono_class_from_name_checked (image, name_space, name, &error);
8057         if (!klass)
8058                 g_error ("Runtime critical type %s.%s not found", name_space, name);
8059         if (!mono_error_ok (&error))
8060                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8061         return klass;
8062 }
8063
8064 /**
8065  * mono_class_try_load_from_name:
8066  * @image: The MonoImage where the type is looked up in
8067  * @name_space: the type namespace
8068  * @name: the type short name.
8069  *
8070  * This function tries to load a type, returning the class was found or NULL otherwise.
8071  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8072  *
8073  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8074  * a type that we would otherwise assume to be available but was not due some error.
8075  *
8076  */
8077 MonoClass*
8078 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8079 {
8080         MonoError error;
8081         MonoClass *klass;
8082
8083         klass = mono_class_from_name_checked (image, name_space, name, &error);
8084         if (!mono_error_ok (&error))
8085                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8086         return klass;
8087 }
8088
8089
8090 /**
8091  * mono_class_is_subclass_of:
8092  * @klass: class to probe if it is a subclass of another one
8093  * @klassc: the class we suspect is the base class
8094  * @check_interfaces: whether we should perform interface checks
8095  *
8096  * This method determines whether @klass is a subclass of @klassc.
8097  *
8098  * If the @check_interfaces flag is set, then if @klassc is an interface
8099  * this method return TRUE if the @klass implements the interface or
8100  * if @klass is an interface, if one of its base classes is @klass.
8101  *
8102  * If @check_interfaces is false then, then if @klass is not an interface
8103  * then it returns TRUE if the @klass is a subclass of @klassc.
8104  *
8105  * if @klass is an interface and @klassc is System.Object, then this function
8106  * return true.
8107  *
8108  */
8109 gboolean
8110 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
8111                            gboolean check_interfaces)
8112 {
8113 /*FIXME test for interfaces with variant generic arguments*/
8114         
8115         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8116                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8117                         return TRUE;
8118         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8119                 int i;
8120
8121                 for (i = 0; i < klass->interface_count; i ++) {
8122                         MonoClass *ic =  klass->interfaces [i];
8123                         if (ic == klassc)
8124                                 return TRUE;
8125                 }
8126         } else {
8127                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8128                         return TRUE;
8129         }
8130
8131         /* 
8132          * MS.NET thinks interfaces are a subclass of Object, so we think it as
8133          * well.
8134          */
8135         if (klassc == mono_defaults.object_class)
8136                 return TRUE;
8137
8138         return FALSE;
8139 }
8140
8141 static gboolean
8142 mono_type_is_generic_argument (MonoType *type)
8143 {
8144         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8145 }
8146
8147 gboolean
8148 mono_class_has_variant_generic_params (MonoClass *klass)
8149 {
8150         int i;
8151         MonoGenericContainer *container;
8152
8153         if (!klass->generic_class)
8154                 return FALSE;
8155
8156         container = klass->generic_class->container_class->generic_container;
8157
8158         for (i = 0; i < container->type_argc; ++i)
8159                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8160                         return TRUE;
8161
8162         return FALSE;
8163 }
8164
8165 static gboolean
8166 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8167 {
8168         if (target == candidate)
8169                 return TRUE;
8170
8171         if (check_for_reference_conv &&
8172                 mono_type_is_generic_argument (&target->byval_arg) &&
8173                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8174                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8175                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8176
8177                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8178                         return FALSE;
8179         }
8180         if (!mono_class_is_assignable_from (target, candidate))
8181                 return FALSE;
8182         return TRUE;
8183 }
8184
8185 /**
8186  * @container the generic container from the GTD
8187  * @klass: the class to be assigned to
8188  * @oklass: the source class
8189  * 
8190  * Both @klass and @oklass must be instances of the same generic interface.
8191  *
8192  * Returns: TRUE if @klass can be assigned to a @klass variable
8193  */
8194 gboolean
8195 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8196 {
8197         int j;
8198         MonoType **klass_argv, **oklass_argv;
8199         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8200         MonoGenericContainer *container = klass_gtd->generic_container;
8201
8202         if (klass == oklass)
8203                 return TRUE;
8204
8205         /*Viable candidates are instances of the same generic interface*/
8206         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8207                 return FALSE;
8208
8209         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8210         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8211
8212         for (j = 0; j < container->type_argc; ++j) {
8213                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8214                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8215
8216                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8217                         return FALSE;
8218
8219                 /*
8220                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8221                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8222                  */
8223                 if (param1_class != param2_class) {
8224                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8225                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8226                                         return FALSE;
8227                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8228                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8229                                         return FALSE;
8230                         } else
8231                                 return FALSE;
8232                 }
8233         }
8234         return TRUE;
8235 }
8236
8237 static gboolean
8238 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8239 {
8240         MonoGenericParam *gparam, *ogparam;
8241         MonoGenericParamInfo *tinfo, *cinfo;
8242         MonoClass **candidate_class;
8243         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8244         int tmask, cmask;
8245
8246         if (target == candidate)
8247                 return TRUE;
8248         if (target->byval_arg.type != candidate->byval_arg.type)
8249                 return FALSE;
8250
8251         gparam = target->byval_arg.data.generic_param;
8252         ogparam = candidate->byval_arg.data.generic_param;
8253         tinfo = mono_generic_param_info (gparam);
8254         cinfo = mono_generic_param_info (ogparam);
8255
8256         class_constraint_satisfied = FALSE;
8257         valuetype_constraint_satisfied = FALSE;
8258
8259         /*candidate must have a super set of target's special constraints*/
8260         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8261         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8262
8263         if (cinfo->constraints) {
8264                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8265                         MonoClass *cc = *candidate_class;
8266
8267                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8268                                 class_constraint_satisfied = TRUE;
8269                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8270                                 valuetype_constraint_satisfied = TRUE;
8271                 }
8272         }
8273         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8274         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8275
8276         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8277                 return FALSE;
8278         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8279                 return FALSE;
8280         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8281                 valuetype_constraint_satisfied)) {
8282                 return FALSE;
8283         }
8284
8285
8286         /*candidate type constraints must be a superset of target's*/
8287         if (tinfo->constraints) {
8288                 MonoClass **target_class;
8289                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8290                         MonoClass *tc = *target_class;
8291
8292                         /*
8293                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8294                          * check it's constraints since it satisfy the constraint by itself.
8295                          */
8296                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8297                                 continue;
8298
8299                         if (!cinfo->constraints)
8300                                 return FALSE;
8301
8302                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8303                                 MonoClass *cc = *candidate_class;
8304
8305                                 if (mono_class_is_assignable_from (tc, cc))
8306                                         break;
8307
8308                                 /*
8309                                  * This happens when we have the following:
8310                                  *
8311                                  * Bar<K> where K : IFace
8312                                  * Foo<T, U> where T : U where U : IFace
8313                                  *      ...
8314                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8315                                  *
8316                                  */
8317                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8318                                         if (mono_gparam_is_assignable_from (target, cc))
8319                                                 break;
8320                                 }
8321                         }
8322                         if (!*candidate_class)
8323                                 return FALSE;
8324                 }
8325         }
8326
8327         /*candidate itself must have a constraint that satisfy target*/
8328         if (cinfo->constraints) {
8329                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8330                         MonoClass *cc = *candidate_class;
8331                         if (mono_class_is_assignable_from (target, cc))
8332                                 return TRUE;
8333                 }
8334         }
8335         return FALSE;
8336 }
8337
8338 /**
8339  * mono_class_is_assignable_from:
8340  * @klass: the class to be assigned to
8341  * @oklass: the source class
8342  *
8343  * Returns: TRUE if an instance of object oklass can be assigned to an
8344  * instance of object @klass
8345  */
8346 gboolean
8347 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8348 {
8349         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8350         if (!klass->inited)
8351                 mono_class_init (klass);
8352
8353         if (!oklass->inited)
8354                 mono_class_init (oklass);
8355
8356         if (klass->exception_type || oklass->exception_type)
8357                 return FALSE;
8358
8359         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8360                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8361                         return FALSE;
8362                 return mono_gparam_is_assignable_from (klass, oklass);
8363         }
8364
8365         if (MONO_CLASS_IS_INTERFACE (klass)) {
8366                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8367                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8368                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8369                         int i;
8370
8371                         if (constraints) {
8372                                 for (i = 0; constraints [i]; ++i) {
8373                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8374                                                 return TRUE;
8375                                 }
8376                         }
8377
8378                         return FALSE;
8379                 }
8380
8381                 /* interface_offsets might not be set for dynamic classes */
8382                 if (oklass->ref_info_handle && !oklass->interface_bitmap)
8383                         /* 
8384                          * oklass might be a generic type parameter but they have 
8385                          * interface_offsets set.
8386                          */
8387                         return mono_reflection_call_is_assignable_to (oklass, klass);
8388                 if (!oklass->interface_bitmap)
8389                         /* Happens with generic instances of not-yet created dynamic types */
8390                         return FALSE;
8391                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8392                         return TRUE;
8393
8394                 if (mono_class_has_variant_generic_params (klass)) {
8395                         MonoError error;
8396                         int i;
8397                         mono_class_setup_interfaces (oklass, &error);
8398                         if (!mono_error_ok (&error)) {
8399                                 mono_error_cleanup (&error);
8400                                 return FALSE;
8401                         }
8402
8403                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8404                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8405                                 MonoClass *iface = oklass->interfaces_packed [i];
8406
8407                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8408                                         return TRUE;
8409                         }
8410                 }
8411                 return FALSE;
8412         } else if (klass->delegate) {
8413                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8414                         return TRUE;
8415         }else if (klass->rank) {
8416                 MonoClass *eclass, *eoclass;
8417
8418                 if (oklass->rank != klass->rank)
8419                         return FALSE;
8420
8421                 /* vectors vs. one dimensional arrays */
8422                 if (oklass->byval_arg.type != klass->byval_arg.type)
8423                         return FALSE;
8424
8425                 eclass = klass->cast_class;
8426                 eoclass = oklass->cast_class;
8427
8428                 /* 
8429                  * a is b does not imply a[] is b[] when a is a valuetype, and
8430                  * b is a reference type.
8431                  */
8432
8433                 if (eoclass->valuetype) {
8434                         if ((eclass == mono_defaults.enum_class) || 
8435                                 (eclass == mono_defaults.enum_class->parent) ||
8436                                 (eclass == mono_defaults.object_class))
8437                                 return FALSE;
8438                 }
8439
8440                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8441         } else if (mono_class_is_nullable (klass)) {
8442                 if (mono_class_is_nullable (oklass))
8443                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8444                 else
8445                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8446         } else if (klass == mono_defaults.object_class)
8447                 return TRUE;
8448
8449         return mono_class_has_parent (oklass, klass);
8450 }       
8451
8452 /*Check if @oklass is variant compatible with @klass.*/
8453 static gboolean
8454 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8455 {
8456         int j;
8457         MonoType **klass_argv, **oklass_argv;
8458         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8459         MonoGenericContainer *container = klass_gtd->generic_container;
8460
8461         /*Viable candidates are instances of the same generic interface*/
8462         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8463                 return FALSE;
8464
8465         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8466         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8467
8468         for (j = 0; j < container->type_argc; ++j) {
8469                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8470                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8471
8472                 if (param1_class->valuetype != param2_class->valuetype)
8473                         return FALSE;
8474
8475                 /*
8476                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8477                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8478                  */
8479                 if (param1_class != param2_class) {
8480                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8481                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8482                                         return FALSE;
8483                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8484                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8485                                         return FALSE;
8486                         } else
8487                                 return FALSE;
8488                 }
8489         }
8490         return TRUE;
8491 }
8492 /*Check if @candidate implements the interface @target*/
8493 static gboolean
8494 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8495 {
8496         MonoError error;
8497         int i;
8498         gboolean is_variant = mono_class_has_variant_generic_params (target);
8499
8500         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8501                 if (mono_class_is_variant_compatible_slow (target, candidate))
8502                         return TRUE;
8503         }
8504
8505         do {
8506                 if (candidate == target)
8507                         return TRUE;
8508
8509                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8510                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8511                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8512                         int j;
8513                         if (tb && tb->interfaces) {
8514                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8515                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8516                                         MonoClass *iface_class;
8517
8518                                         /* we can't realize the type here since it can do pretty much anything. */
8519                                         if (!iface->type)
8520                                                 continue;
8521                                         iface_class = mono_class_from_mono_type (iface->type);
8522                                         if (iface_class == target)
8523                                                 return TRUE;
8524                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8525                                                 return TRUE;
8526                                         if (mono_class_implement_interface_slow (target, iface_class))
8527                                                 return TRUE;
8528                                 }
8529                         }
8530                 } else {
8531                         /*setup_interfaces don't mono_class_init anything*/
8532                         /*FIXME this doesn't handle primitive type arrays.
8533                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8534                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8535                         */
8536                         mono_class_setup_interfaces (candidate, &error);
8537                         if (!mono_error_ok (&error)) {
8538                                 mono_error_cleanup (&error);
8539                                 return FALSE;
8540                         }
8541
8542                         for (i = 0; i < candidate->interface_count; ++i) {
8543                                 if (candidate->interfaces [i] == target)
8544                                         return TRUE;
8545                                 
8546                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8547                                         return TRUE;
8548
8549                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8550                                         return TRUE;
8551                         }
8552                 }
8553                 candidate = candidate->parent;
8554         } while (candidate);
8555
8556         return FALSE;
8557 }
8558
8559 /*
8560  * Check if @oklass can be assigned to @klass.
8561  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8562  */
8563 gboolean
8564 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8565 {
8566         if (candidate == target)
8567                 return TRUE;
8568         if (target == mono_defaults.object_class)
8569                 return TRUE;
8570
8571         if (mono_class_has_parent (candidate, target))
8572                 return TRUE;
8573
8574         /*If target is not an interface there is no need to check them.*/
8575         if (MONO_CLASS_IS_INTERFACE (target))
8576                 return mono_class_implement_interface_slow (target, candidate);
8577
8578         if (target->delegate && mono_class_has_variant_generic_params (target))
8579                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8580
8581         if (target->rank) {
8582                 MonoClass *eclass, *eoclass;
8583
8584                 if (target->rank != candidate->rank)
8585                         return FALSE;
8586
8587                 /* vectors vs. one dimensional arrays */
8588                 if (target->byval_arg.type != candidate->byval_arg.type)
8589                         return FALSE;
8590
8591                 eclass = target->cast_class;
8592                 eoclass = candidate->cast_class;
8593
8594                 /*
8595                  * a is b does not imply a[] is b[] when a is a valuetype, and
8596                  * b is a reference type.
8597                  */
8598
8599                 if (eoclass->valuetype) {
8600                         if ((eclass == mono_defaults.enum_class) ||
8601                                 (eclass == mono_defaults.enum_class->parent) ||
8602                                 (eclass == mono_defaults.object_class))
8603                                 return FALSE;
8604                 }
8605
8606                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8607         }
8608         /*FIXME properly handle nullables */
8609         /*FIXME properly handle (M)VAR */
8610         return FALSE;
8611 }
8612
8613 /**
8614  * mono_class_get_cctor:
8615  * @klass: A MonoClass pointer
8616  *
8617  * Returns: The static constructor of @klass if it exists, NULL otherwise.
8618  */
8619 MonoMethod*
8620 mono_class_get_cctor (MonoClass *klass)
8621 {
8622         MonoCachedClassInfo cached_info;
8623
8624         if (image_is_dynamic (klass->image)) {
8625                 /* 
8626                  * has_cctor is not set for these classes because mono_class_init () is
8627                  * not run for them.
8628                  */
8629                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8630         }
8631
8632         if (!klass->has_cctor)
8633                 return NULL;
8634
8635         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8636                 MonoError error;
8637                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8638                 if (!mono_error_ok (&error))
8639                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8640                 return result;
8641         }
8642
8643         if (klass->generic_class && !klass->methods)
8644                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8645
8646         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8647 }
8648
8649 /**
8650  * mono_class_get_finalizer:
8651  * @klass: The MonoClass pointer
8652  *
8653  * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8654  */
8655 MonoMethod*
8656 mono_class_get_finalizer (MonoClass *klass)
8657 {
8658         MonoCachedClassInfo cached_info;
8659
8660         if (!klass->inited)
8661                 mono_class_init (klass);
8662         if (!mono_class_has_finalizer (klass))
8663                 return NULL;
8664
8665         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8666                 MonoError error;
8667                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8668                 if (!mono_error_ok (&error))
8669                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8670                 return result;
8671         }else {
8672                 mono_class_setup_vtable (klass);
8673                 return klass->vtable [finalize_slot];
8674         }
8675 }
8676
8677 /**
8678  * mono_class_needs_cctor_run:
8679  * @klass: the MonoClass pointer
8680  * @caller: a MonoMethod describing the caller
8681  *
8682  * Determines whenever the class has a static constructor and whenever it
8683  * needs to be called when executing CALLER.
8684  */
8685 gboolean
8686 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8687 {
8688         MonoMethod *method;
8689
8690         method = mono_class_get_cctor (klass);
8691         if (method)
8692                 return (method == caller) ? FALSE : TRUE;
8693         else
8694                 return FALSE;
8695 }
8696
8697 /**
8698  * mono_class_array_element_size:
8699  * @klass: 
8700  *
8701  * Returns: The number of bytes an element of type @klass
8702  * uses when stored into an array.
8703  */
8704 gint32
8705 mono_class_array_element_size (MonoClass *klass)
8706 {
8707         MonoType *type = &klass->byval_arg;
8708         
8709 handle_enum:
8710         switch (type->type) {
8711         case MONO_TYPE_I1:
8712         case MONO_TYPE_U1:
8713         case MONO_TYPE_BOOLEAN:
8714                 return 1;
8715         case MONO_TYPE_I2:
8716         case MONO_TYPE_U2:
8717         case MONO_TYPE_CHAR:
8718                 return 2;
8719         case MONO_TYPE_I4:
8720         case MONO_TYPE_U4:
8721         case MONO_TYPE_R4:
8722                 return 4;
8723         case MONO_TYPE_I:
8724         case MONO_TYPE_U:
8725         case MONO_TYPE_PTR:
8726         case MONO_TYPE_CLASS:
8727         case MONO_TYPE_STRING:
8728         case MONO_TYPE_OBJECT:
8729         case MONO_TYPE_SZARRAY:
8730         case MONO_TYPE_ARRAY: 
8731                 return sizeof (gpointer);
8732         case MONO_TYPE_I8:
8733         case MONO_TYPE_U8:
8734         case MONO_TYPE_R8:
8735                 return 8;
8736         case MONO_TYPE_VALUETYPE:
8737                 if (type->data.klass->enumtype) {
8738                         type = mono_class_enum_basetype (type->data.klass);
8739                         klass = klass->element_class;
8740                         goto handle_enum;
8741                 }
8742                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8743         case MONO_TYPE_GENERICINST:
8744                 type = &type->data.generic_class->container_class->byval_arg;
8745                 goto handle_enum;
8746         case MONO_TYPE_VAR:
8747         case MONO_TYPE_MVAR: {
8748                 int align;
8749
8750                 return mono_type_size (type, &align);
8751         }
8752         case MONO_TYPE_VOID:
8753                 return 0;
8754                 
8755         default:
8756                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8757         }
8758         return -1;
8759 }
8760
8761 /**
8762  * mono_array_element_size:
8763  * @ac: pointer to a #MonoArrayClass
8764  *
8765  * Returns: The size of single array element.
8766  */
8767 gint32
8768 mono_array_element_size (MonoClass *ac)
8769 {
8770         g_assert (ac->rank);
8771         return ac->sizes.element_size;
8772 }
8773
8774 gpointer
8775 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8776               MonoGenericContext *context)
8777 {
8778         MonoError error;
8779         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8780         g_assert (mono_error_ok (&error));
8781         return res;
8782 }
8783
8784 gpointer
8785 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8786               MonoGenericContext *context, MonoError *error)
8787 {
8788         mono_error_init (error);
8789
8790         if (image_is_dynamic (image)) {
8791                 MonoClass *tmp_handle_class;
8792                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8793
8794                 g_assert (tmp_handle_class);
8795                 if (handle_class)
8796                         *handle_class = tmp_handle_class;
8797
8798                 if (tmp_handle_class == mono_defaults.typehandle_class)
8799                         return &((MonoClass*)obj)->byval_arg;
8800                 else
8801                         return obj;
8802         }
8803
8804         switch (token & 0xff000000) {
8805         case MONO_TOKEN_TYPE_DEF:
8806         case MONO_TOKEN_TYPE_REF:
8807         case MONO_TOKEN_TYPE_SPEC: {
8808                 MonoType *type;
8809                 if (handle_class)
8810                         *handle_class = mono_defaults.typehandle_class;
8811                 type = mono_type_get_checked (image, token, context, error);
8812                 if (!type)
8813                         return NULL;
8814
8815                 mono_class_init (mono_class_from_mono_type (type));
8816                 /* We return a MonoType* as handle */
8817                 return type;
8818         }
8819         case MONO_TOKEN_FIELD_DEF: {
8820                 MonoClass *klass;
8821                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8822                 if (!type) {
8823                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8824                         return NULL;
8825                 }
8826                 if (handle_class)
8827                         *handle_class = mono_defaults.fieldhandle_class;
8828                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8829                 if (!klass)
8830                         return NULL;
8831
8832                 mono_class_init (klass);
8833                 return mono_class_get_field (klass, token);
8834         }
8835         case MONO_TOKEN_METHOD_DEF:
8836         case MONO_TOKEN_METHOD_SPEC: {
8837                 MonoMethod *meth;
8838                 meth = mono_get_method_checked (image, token, NULL, context, error);
8839                 if (handle_class)
8840                         *handle_class = mono_defaults.methodhandle_class;
8841                 if (!meth)
8842                         return NULL;
8843
8844                 return meth;
8845         }
8846         case MONO_TOKEN_MEMBER_REF: {
8847                 guint32 cols [MONO_MEMBERREF_SIZE];
8848                 const char *sig;
8849                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8850                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8851                 mono_metadata_decode_blob_size (sig, &sig);
8852                 if (*sig == 0x6) { /* it's a field */
8853                         MonoClass *klass;
8854                         MonoClassField *field;
8855                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8856                         if (handle_class)
8857                                 *handle_class = mono_defaults.fieldhandle_class;
8858                         return field;
8859                 } else {
8860                         MonoMethod *meth;
8861                         meth = mono_get_method_checked (image, token, NULL, context, error);
8862                         if (handle_class)
8863                                 *handle_class = mono_defaults.methodhandle_class;
8864                         return meth;
8865                 }
8866         }
8867         default:
8868                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8869         }
8870         return NULL;
8871 }
8872
8873 /**
8874  * This function might need to call runtime functions so it can't be part
8875  * of the metadata library.
8876  */
8877 static MonoLookupDynamicToken lookup_dynamic = NULL;
8878
8879 void
8880 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8881 {
8882         lookup_dynamic = func;
8883 }
8884
8885 gpointer
8886 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8887 {
8888         MonoClass *handle_class;
8889
8890         return lookup_dynamic (image, token, TRUE, &handle_class, context);
8891 }
8892
8893 gpointer
8894 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8895 {
8896         return lookup_dynamic (image, token, valid_token, handle_class, context);
8897 }
8898
8899 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8900
8901 void
8902 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8903 {
8904         get_cached_class_info = func;
8905 }
8906
8907 static gboolean
8908 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8909 {
8910         if (!get_cached_class_info)
8911                 return FALSE;
8912         else
8913                 return get_cached_class_info (klass, res);
8914 }
8915
8916 void
8917 mono_install_get_class_from_name (MonoGetClassFromName func)
8918 {
8919         get_class_from_name = func;
8920 }
8921
8922 /**
8923  * mono_class_get_image:
8924  *
8925  * Use this method to get the `MonoImage*` where this class came from.
8926  *
8927  * Returns: The image where this class is defined.
8928  */
8929 MonoImage*
8930 mono_class_get_image (MonoClass *klass)
8931 {
8932         return klass->image;
8933 }
8934
8935 /**
8936  * mono_class_get_element_class:
8937  * @klass: the MonoClass to act on
8938  *
8939  * Use this function to get the element class of an array.
8940  *
8941  * Returns: The element class of an array.
8942  */
8943 MonoClass*
8944 mono_class_get_element_class (MonoClass *klass)
8945 {
8946         return klass->element_class;
8947 }
8948
8949 /**
8950  * mono_class_is_valuetype:
8951  * @klass: the MonoClass to act on
8952  *
8953  * Use this method to determine if the provided `MonoClass*` represents a value type,
8954  * or a reference type.
8955  *
8956  * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8957  */
8958 gboolean
8959 mono_class_is_valuetype (MonoClass *klass)
8960 {
8961         return klass->valuetype;
8962 }
8963
8964 /**
8965  * mono_class_is_enum:
8966  * @klass: the MonoClass to act on
8967  *
8968  * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8969  *
8970  * Returns: TRUE if the MonoClass represents an enumeration.
8971  */
8972 gboolean
8973 mono_class_is_enum (MonoClass *klass)
8974 {
8975         return klass->enumtype;
8976 }
8977
8978 /**
8979  * mono_class_enum_basetype:
8980  * @klass: the MonoClass to act on
8981  *
8982  * Use this function to get the underlying type for an enumeration value.
8983  * 
8984  * Returns: The underlying type representation for an enumeration.
8985  */
8986 MonoType*
8987 mono_class_enum_basetype (MonoClass *klass)
8988 {
8989         if (klass->element_class == klass)
8990                 /* SRE or broken types */
8991                 return NULL;
8992         else
8993                 return &klass->element_class->byval_arg;
8994 }
8995
8996 /**
8997  * mono_class_get_parent
8998  * @klass: the MonoClass to act on
8999  *
9000  * Returns: The parent class for this class.
9001  */
9002 MonoClass*
9003 mono_class_get_parent (MonoClass *klass)
9004 {
9005         return klass->parent;
9006 }
9007
9008 /**
9009  * mono_class_get_nesting_type:
9010  * @klass: the MonoClass to act on
9011  *
9012  * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9013  *
9014  * If the return is NULL, this indicates that this class is not nested.
9015  *
9016  * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9017  */
9018 MonoClass*
9019 mono_class_get_nesting_type (MonoClass *klass)
9020 {
9021         return klass->nested_in;
9022 }
9023
9024 /**
9025  * mono_class_get_rank:
9026  * @klass: the MonoClass to act on
9027  *
9028  * Returns: The rank for the array (the number of dimensions).
9029  */
9030 int
9031 mono_class_get_rank (MonoClass *klass)
9032 {
9033         return klass->rank;
9034 }
9035
9036 /**
9037  * mono_class_get_flags:
9038  * @klass: the MonoClass to act on
9039  *
9040  * The type flags from the TypeDef table from the metadata.
9041  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9042  * different values.
9043  *
9044  * Returns: The flags from the TypeDef table.
9045  */
9046 guint32
9047 mono_class_get_flags (MonoClass *klass)
9048 {
9049         return klass->flags;
9050 }
9051
9052 /**
9053  * mono_class_get_name
9054  * @klass: the MonoClass to act on
9055  *
9056  * Returns: The name of the class.
9057  */
9058 const char*
9059 mono_class_get_name (MonoClass *klass)
9060 {
9061         return klass->name;
9062 }
9063
9064 /**
9065  * mono_class_get_namespace:
9066  * @klass: the MonoClass to act on
9067  *
9068  * Returns: The namespace of the class.
9069  */
9070 const char*
9071 mono_class_get_namespace (MonoClass *klass)
9072 {
9073         return klass->name_space;
9074 }
9075
9076 /**
9077  * mono_class_get_type:
9078  * @klass: the MonoClass to act on
9079  *
9080  * This method returns the internal Type representation for the class.
9081  *
9082  * Returns: The MonoType from the class.
9083  */
9084 MonoType*
9085 mono_class_get_type (MonoClass *klass)
9086 {
9087         return &klass->byval_arg;
9088 }
9089
9090 /**
9091  * mono_class_get_type_token:
9092  * @klass: the MonoClass to act on
9093  *
9094  * This method returns type token for the class.
9095  *
9096  * Returns: The type token for the class.
9097  */
9098 guint32
9099 mono_class_get_type_token (MonoClass *klass)
9100 {
9101   return klass->type_token;
9102 }
9103
9104 /**
9105  * mono_class_get_byref_type:
9106  * @klass: the MonoClass to act on
9107  *
9108  * 
9109  */
9110 MonoType*
9111 mono_class_get_byref_type (MonoClass *klass)
9112 {
9113         return &klass->this_arg;
9114 }
9115
9116 /**
9117  * mono_class_num_fields:
9118  * @klass: the MonoClass to act on
9119  *
9120  * Returns: The number of static and instance fields in the class.
9121  */
9122 int
9123 mono_class_num_fields (MonoClass *klass)
9124 {
9125         return klass->field.count;
9126 }
9127
9128 /**
9129  * mono_class_num_methods:
9130  * @klass: the MonoClass to act on
9131  *
9132  * Returns: The number of methods in the class.
9133  */
9134 int
9135 mono_class_num_methods (MonoClass *klass)
9136 {
9137         return klass->method.count;
9138 }
9139
9140 /**
9141  * mono_class_num_properties
9142  * @klass: the MonoClass to act on
9143  *
9144  * Returns: The number of properties in the class.
9145  */
9146 int
9147 mono_class_num_properties (MonoClass *klass)
9148 {
9149         mono_class_setup_properties (klass);
9150
9151         return klass->ext->property.count;
9152 }
9153
9154 /**
9155  * mono_class_num_events:
9156  * @klass: the MonoClass to act on
9157  *
9158  * Returns: The number of events in the class.
9159  */
9160 int
9161 mono_class_num_events (MonoClass *klass)
9162 {
9163         mono_class_setup_events (klass);
9164
9165         return klass->ext->event.count;
9166 }
9167
9168 /**
9169  * mono_class_get_fields:
9170  * @klass: the MonoClass to act on
9171  *
9172  * This routine is an iterator routine for retrieving the fields in a class.
9173  *
9174  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9175  * iterate over all of the elements.  When no more values are
9176  * available, the return value is NULL.
9177  *
9178  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9179  */
9180 MonoClassField*
9181 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9182 {
9183         MonoClassField* field;
9184         if (!iter)
9185                 return NULL;
9186         if (!*iter) {
9187                 mono_class_setup_fields_locking (klass);
9188                 if (klass->exception_type)
9189                         return NULL;
9190                 /* start from the first */
9191                 if (klass->field.count) {
9192                         *iter = &klass->fields [0];
9193                         return &klass->fields [0];
9194                 } else {
9195                         /* no fields */
9196                         return NULL;
9197                 }
9198         }
9199         field = (MonoClassField *)*iter;
9200         field++;
9201         if (field < &klass->fields [klass->field.count]) {
9202                 *iter = field;
9203                 return field;
9204         }
9205         return NULL;
9206 }
9207
9208 /**
9209  * mono_class_get_methods
9210  * @klass: the MonoClass to act on
9211  *
9212  * This routine is an iterator routine for retrieving the fields in a class.
9213  *
9214  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9215  * iterate over all of the elements.  When no more values are
9216  * available, the return value is NULL.
9217  *
9218  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9219  */
9220 MonoMethod*
9221 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9222 {
9223         MonoMethod** method;
9224         if (!iter)
9225                 return NULL;
9226         if (!*iter) {
9227                 mono_class_setup_methods (klass);
9228
9229                 /*
9230                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9231                  * FIXME we should better report this error to the caller
9232                  */
9233                 if (!klass->methods)
9234                         return NULL;
9235                 /* start from the first */
9236                 if (klass->method.count) {
9237                         *iter = &klass->methods [0];
9238                         return klass->methods [0];
9239                 } else {
9240                         /* no method */
9241                         return NULL;
9242                 }
9243         }
9244         method = (MonoMethod **)*iter;
9245         method++;
9246         if (method < &klass->methods [klass->method.count]) {
9247                 *iter = method;
9248                 return *method;
9249         }
9250         return NULL;
9251 }
9252
9253 /*
9254  * mono_class_get_virtual_methods:
9255  *
9256  *   Iterate over the virtual methods of KLASS.
9257  *
9258  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9259  */
9260 static MonoMethod*
9261 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9262 {
9263         MonoMethod** method;
9264         if (!iter)
9265                 return NULL;
9266         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9267                 if (!*iter) {
9268                         mono_class_setup_methods (klass);
9269                         /*
9270                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9271                          * FIXME we should better report this error to the caller
9272                          */
9273                         if (!klass->methods)
9274                                 return NULL;
9275                         /* start from the first */
9276                         method = &klass->methods [0];
9277                 } else {
9278                         method = (MonoMethod **)*iter;
9279                         method++;
9280                 }
9281                 while (method < &klass->methods [klass->method.count]) {
9282                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9283                                 break;
9284                         method ++;
9285                 }
9286                 if (method < &klass->methods [klass->method.count]) {
9287                         *iter = method;
9288                         return *method;
9289                 } else {
9290                         return NULL;
9291                 }
9292         } else {
9293                 /* Search directly in metadata to avoid calling setup_methods () */
9294                 MonoMethod *res = NULL;
9295                 int i, start_index;
9296
9297                 if (!*iter) {
9298                         start_index = 0;
9299                 } else {
9300                         start_index = GPOINTER_TO_UINT (*iter);
9301                 }
9302
9303                 for (i = start_index; i < klass->method.count; ++i) {
9304                         guint32 flags;
9305
9306                         /* klass->method.first points into the methodptr table */
9307                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9308
9309                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9310                                 break;
9311                 }
9312
9313                 if (i < klass->method.count) {
9314                         MonoError error;
9315                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9316                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9317
9318                         /* Add 1 here so the if (*iter) check fails */
9319                         *iter = GUINT_TO_POINTER (i + 1);
9320                         return res;
9321                 } else {
9322                         return NULL;
9323                 }
9324         }
9325 }
9326
9327 /**
9328  * mono_class_get_properties:
9329  * @klass: the MonoClass to act on
9330  *
9331  * This routine is an iterator routine for retrieving the properties in a class.
9332  *
9333  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9334  * iterate over all of the elements.  When no more values are
9335  * available, the return value is NULL.
9336  *
9337  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9338  */
9339 MonoProperty*
9340 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9341 {
9342         MonoProperty* property;
9343         if (!iter)
9344                 return NULL;
9345         if (!*iter) {
9346                 mono_class_setup_properties (klass);
9347                 /* start from the first */
9348                 if (klass->ext->property.count) {
9349                         *iter = &klass->ext->properties [0];
9350                         return (MonoProperty *)*iter;
9351                 } else {
9352                         /* no fields */
9353                         return NULL;
9354                 }
9355         }
9356         property = (MonoProperty *)*iter;
9357         property++;
9358         if (property < &klass->ext->properties [klass->ext->property.count]) {
9359                 *iter = property;
9360                 return (MonoProperty *)*iter;
9361         }
9362         return NULL;
9363 }
9364
9365 /**
9366  * mono_class_get_events:
9367  * @klass: the MonoClass to act on
9368  *
9369  * This routine is an iterator routine for retrieving the properties in a class.
9370  *
9371  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9372  * iterate over all of the elements.  When no more values are
9373  * available, the return value is NULL.
9374  *
9375  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9376  */
9377 MonoEvent*
9378 mono_class_get_events (MonoClass* klass, gpointer *iter)
9379 {
9380         MonoEvent* event;
9381         if (!iter)
9382                 return NULL;
9383         if (!*iter) {
9384                 mono_class_setup_events (klass);
9385                 /* start from the first */
9386                 if (klass->ext->event.count) {
9387                         *iter = &klass->ext->events [0];
9388                         return (MonoEvent *)*iter;
9389                 } else {
9390                         /* no fields */
9391                         return NULL;
9392                 }
9393         }
9394         event = (MonoEvent *)*iter;
9395         event++;
9396         if (event < &klass->ext->events [klass->ext->event.count]) {
9397                 *iter = event;
9398                 return (MonoEvent *)*iter;
9399         }
9400         return NULL;
9401 }
9402
9403 /**
9404  * mono_class_get_interfaces
9405  * @klass: the MonoClass to act on
9406  *
9407  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9408  *
9409  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9410  * iterate over all of the elements.  When no more values are
9411  * available, the return value is NULL.
9412  *
9413  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9414  */
9415 MonoClass*
9416 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9417 {
9418         MonoError error;
9419         MonoClass** iface;
9420         if (!iter)
9421                 return NULL;
9422         if (!*iter) {
9423                 if (!klass->inited)
9424                         mono_class_init (klass);
9425                 if (!klass->interfaces_inited) {
9426                         mono_class_setup_interfaces (klass, &error);
9427                         if (!mono_error_ok (&error)) {
9428                                 mono_error_cleanup (&error);
9429                                 return NULL;
9430                         }
9431                 }
9432                 /* start from the first */
9433                 if (klass->interface_count) {
9434                         *iter = &klass->interfaces [0];
9435                         return klass->interfaces [0];
9436                 } else {
9437                         /* no interface */
9438                         return NULL;
9439                 }
9440         }
9441         iface = (MonoClass **)*iter;
9442         iface++;
9443         if (iface < &klass->interfaces [klass->interface_count]) {
9444                 *iter = iface;
9445                 return *iface;
9446         }
9447         return NULL;
9448 }
9449
9450 static void
9451 setup_nested_types (MonoClass *klass)
9452 {
9453         MonoError error;
9454         GList *classes, *nested_classes, *l;
9455         int i;
9456
9457         if (klass->nested_classes_inited)
9458                 return;
9459
9460         if (!klass->type_token)
9461                 klass->nested_classes_inited = TRUE;
9462
9463         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9464         classes = NULL;
9465         while (i) {
9466                 MonoClass* nclass;
9467                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9468                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9469                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9470                 if (!mono_error_ok (&error)) {
9471                         /*FIXME don't swallow the error message*/
9472                         mono_error_cleanup (&error);
9473
9474                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9475                         continue;
9476                 }
9477
9478                 classes = g_list_prepend (classes, nclass);
9479
9480                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9481         }
9482
9483         mono_class_alloc_ext (klass);
9484
9485         nested_classes = NULL;
9486         for (l = classes; l; l = l->next)
9487                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9488         g_list_free (classes);
9489
9490         mono_image_lock (klass->image);
9491
9492         mono_memory_barrier ();
9493         if (!klass->nested_classes_inited) {
9494                 klass->ext->nested_classes = nested_classes;
9495                 mono_memory_barrier ();
9496                 klass->nested_classes_inited = TRUE;
9497         }
9498
9499         mono_image_unlock (klass->image);
9500 }
9501
9502 /**
9503  * mono_class_get_nested_types
9504  * @klass: the MonoClass to act on
9505  *
9506  * This routine is an iterator routine for retrieving the nested types of a class.
9507  * This works only if @klass is non-generic, or a generic type definition.
9508  *
9509  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9510  * iterate over all of the elements.  When no more values are
9511  * available, the return value is NULL.
9512  *
9513  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9514  */
9515 MonoClass*
9516 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9517 {
9518         GList *item;
9519
9520         if (!iter)
9521                 return NULL;
9522         if (!klass->nested_classes_inited)
9523                 setup_nested_types (klass);
9524
9525         if (!*iter) {
9526                 /* start from the first */
9527                 if (klass->ext && klass->ext->nested_classes) {
9528                         *iter = klass->ext->nested_classes;
9529                         return (MonoClass *)klass->ext->nested_classes->data;
9530                 } else {
9531                         /* no nested types */
9532                         return NULL;
9533                 }
9534         }
9535         item = (GList *)*iter;
9536         item = item->next;
9537         if (item) {
9538                 *iter = item;
9539                 return (MonoClass *)item->data;
9540         }
9541         return NULL;
9542 }
9543
9544
9545 /**
9546  * mono_class_is_delegate
9547  * @klass: the MonoClass to act on
9548  *
9549  * Returns: TRUE if the MonoClass represents a System.Delegate.
9550  */
9551 mono_bool
9552 mono_class_is_delegate (MonoClass *klass)
9553 {
9554         return klass->delegate;
9555 }
9556
9557 /**
9558  * mono_class_implements_interface
9559  * @klass: The MonoClass to act on
9560  * @interface: The interface to check if @klass implements.
9561  *
9562  * Returns: TRUE if @klass implements @interface.
9563  */
9564 mono_bool
9565 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9566 {
9567         return mono_class_is_assignable_from (iface, klass);
9568 }
9569
9570 /**
9571  * mono_field_get_name:
9572  * @field: the MonoClassField to act on
9573  *
9574  * Returns: The name of the field.
9575  */
9576 const char*
9577 mono_field_get_name (MonoClassField *field)
9578 {
9579         return field->name;
9580 }
9581
9582 /**
9583  * mono_field_get_type:
9584  * @field: the MonoClassField to act on
9585  *
9586  * Returns: MonoType of the field.
9587  */
9588 MonoType*
9589 mono_field_get_type (MonoClassField *field)
9590 {
9591         MonoError error;
9592         MonoType *type = mono_field_get_type_checked (field, &error);
9593         if (!mono_error_ok (&error)) {
9594                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9595                 mono_error_cleanup (&error);
9596         }
9597         return type;
9598 }
9599
9600
9601 /**
9602  * mono_field_get_type_checked:
9603  * @field: the MonoClassField to act on
9604  * @error: used to return any erro found while retrieving @field type
9605  *
9606  * Returns: MonoType of the field.
9607  */
9608 MonoType*
9609 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9610 {
9611         mono_error_init (error);
9612         if (!field->type)
9613                 mono_field_resolve_type (field, error);
9614         return field->type;
9615 }
9616
9617 /**
9618  * mono_field_get_parent:
9619  * @field: the MonoClassField to act on
9620  *
9621  * Returns: MonoClass where the field was defined.
9622  */
9623 MonoClass*
9624 mono_field_get_parent (MonoClassField *field)
9625 {
9626         return field->parent;
9627 }
9628
9629 /**
9630  * mono_field_get_flags;
9631  * @field: the MonoClassField to act on
9632  *
9633  * The metadata flags for a field are encoded using the
9634  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9635  *
9636  * Returns: The flags for the field.
9637  */
9638 guint32
9639 mono_field_get_flags (MonoClassField *field)
9640 {
9641         if (!field->type)
9642                 return mono_field_resolve_flags (field);
9643         return field->type->attrs;
9644 }
9645
9646 /**
9647  * mono_field_get_offset:
9648  * @field: the MonoClassField to act on
9649  *
9650  * Returns: The field offset.
9651  */
9652 guint32
9653 mono_field_get_offset (MonoClassField *field)
9654 {
9655         return field->offset;
9656 }
9657
9658 static const char *
9659 mono_field_get_rva (MonoClassField *field)
9660 {
9661         guint32 rva;
9662         int field_index;
9663         MonoClass *klass = field->parent;
9664         MonoFieldDefaultValue *field_def_values;
9665
9666         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9667
9668         if (!klass->ext || !klass->ext->field_def_values) {
9669                 mono_class_alloc_ext (klass);
9670
9671                 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9672
9673                 mono_image_lock (klass->image);
9674                 if (!klass->ext->field_def_values)
9675                         klass->ext->field_def_values = field_def_values;
9676                 mono_image_unlock (klass->image);
9677         }
9678
9679         field_index = mono_field_get_index (field);
9680                 
9681         if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9682                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9683                 if (!rva)
9684                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9685                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9686         }
9687
9688         return klass->ext->field_def_values [field_index].data;
9689 }
9690
9691 /**
9692  * mono_field_get_data:
9693  * @field: the MonoClassField to act on
9694  *
9695  * Returns: A pointer to the metadata constant value or to the field
9696  * data if it has an RVA flag.
9697  */
9698 const char *
9699 mono_field_get_data (MonoClassField *field)
9700 {
9701         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9702                 MonoTypeEnum def_type;
9703
9704                 return mono_class_get_field_default_value (field, &def_type);
9705         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9706                 return mono_field_get_rva (field);
9707         } else {
9708                 return NULL;
9709         }
9710 }
9711
9712 /**
9713  * mono_property_get_name: 
9714  * @prop: the MonoProperty to act on
9715  *
9716  * Returns: The name of the property
9717  */
9718 const char*
9719 mono_property_get_name (MonoProperty *prop)
9720 {
9721         return prop->name;
9722 }
9723
9724 /**
9725  * mono_property_get_set_method
9726  * @prop: the MonoProperty to act on.
9727  *
9728  * Returns: The setter method of the property (A MonoMethod)
9729  */
9730 MonoMethod*
9731 mono_property_get_set_method (MonoProperty *prop)
9732 {
9733         return prop->set;
9734 }
9735
9736 /**
9737  * mono_property_get_get_method
9738  * @prop: the MonoProperty to act on.
9739  *
9740  * Returns: The setter method of the property (A MonoMethod)
9741  */
9742 MonoMethod*
9743 mono_property_get_get_method (MonoProperty *prop)
9744 {
9745         return prop->get;
9746 }
9747
9748 /**
9749  * mono_property_get_parent:
9750  * @prop: the MonoProperty to act on.
9751  *
9752  * Returns: The MonoClass where the property was defined.
9753  */
9754 MonoClass*
9755 mono_property_get_parent (MonoProperty *prop)
9756 {
9757         return prop->parent;
9758 }
9759
9760 /**
9761  * mono_property_get_flags:
9762  * @prop: the MonoProperty to act on.
9763  *
9764  * The metadata flags for a property are encoded using the
9765  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9766  *
9767  * Returns: The flags for the property.
9768  */
9769 guint32
9770 mono_property_get_flags (MonoProperty *prop)
9771 {
9772         return prop->attrs;
9773 }
9774
9775 /**
9776  * mono_event_get_name:
9777  * @event: the MonoEvent to act on
9778  *
9779  * Returns: The name of the event.
9780  */
9781 const char*
9782 mono_event_get_name (MonoEvent *event)
9783 {
9784         return event->name;
9785 }
9786
9787 /**
9788  * mono_event_get_add_method:
9789  * @event: The MonoEvent to act on.
9790  *
9791  * Returns: The @add' method for the event (a MonoMethod).
9792  */
9793 MonoMethod*
9794 mono_event_get_add_method (MonoEvent *event)
9795 {
9796         return event->add;
9797 }
9798
9799 /**
9800  * mono_event_get_remove_method:
9801  * @event: The MonoEvent to act on.
9802  *
9803  * Returns: The @remove method for the event (a MonoMethod).
9804  */
9805 MonoMethod*
9806 mono_event_get_remove_method (MonoEvent *event)
9807 {
9808         return event->remove;
9809 }
9810
9811 /**
9812  * mono_event_get_raise_method:
9813  * @event: The MonoEvent to act on.
9814  *
9815  * Returns: The @raise method for the event (a MonoMethod).
9816  */
9817 MonoMethod*
9818 mono_event_get_raise_method (MonoEvent *event)
9819 {
9820         return event->raise;
9821 }
9822
9823 /**
9824  * mono_event_get_parent:
9825  * @event: the MonoEvent to act on.
9826  *
9827  * Returns: The MonoClass where the event is defined.
9828  */
9829 MonoClass*
9830 mono_event_get_parent (MonoEvent *event)
9831 {
9832         return event->parent;
9833 }
9834
9835 /**
9836  * mono_event_get_flags
9837  * @event: the MonoEvent to act on.
9838  *
9839  * The metadata flags for an event are encoded using the
9840  * EVENT_* constants.  See the tabledefs.h file for details.
9841  *
9842  * Returns: The flags for the event.
9843  */
9844 guint32
9845 mono_event_get_flags (MonoEvent *event)
9846 {
9847         return event->attrs;
9848 }
9849
9850 /**
9851  * mono_class_get_method_from_name:
9852  * @klass: where to look for the method
9853  * @name: name of the method
9854  * @param_count: number of parameters. -1 for any number.
9855  *
9856  * Obtains a MonoMethod with a given name and number of parameters.
9857  * It only works if there are no multiple signatures for any given method name.
9858  */
9859 MonoMethod *
9860 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9861 {
9862         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9863 }
9864
9865 static MonoMethod*
9866 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9867 {
9868         MonoMethod *res = NULL;
9869         int i;
9870
9871         /* Search directly in the metadata to avoid calling setup_methods () */
9872         for (i = 0; i < klass->method.count; ++i) {
9873                 MonoError error;
9874                 guint32 cols [MONO_METHOD_SIZE];
9875                 MonoMethod *method;
9876                 MonoMethodSignature *sig;
9877
9878                 /* klass->method.first points into the methodptr table */
9879                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9880
9881                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9882                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9883                         if (!method) {
9884                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9885                                 continue;
9886                         }
9887                         if (param_count == -1) {
9888                                 res = method;
9889                                 break;
9890                         }
9891                         sig = mono_method_signature_checked (method, &error);
9892                         if (!sig) {
9893                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9894                                 continue;
9895                         }
9896                         if (sig->param_count == param_count) {
9897                                 res = method;
9898                                 break;
9899                         }
9900                 }
9901         }
9902
9903         return res;
9904 }
9905
9906 /**
9907  * mono_class_get_method_from_name_flags:
9908  * @klass: where to look for the method
9909  * @name_space: name of the method
9910  * @param_count: number of parameters. -1 for any number.
9911  * @flags: flags which must be set in the method
9912  *
9913  * Obtains a MonoMethod with a given name and number of parameters.
9914  * It only works if there are no multiple signatures for any given method name.
9915  */
9916 MonoMethod *
9917 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9918 {
9919         MonoMethod *res = NULL;
9920         int i;
9921
9922         mono_class_init (klass);
9923
9924         if (klass->generic_class && !klass->methods) {
9925                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9926                 if (res) {
9927                         MonoError error;
9928                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9929                         if (!mono_error_ok (&error))
9930                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9931                 }
9932                 return res;
9933         }
9934
9935         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9936                 mono_class_setup_methods (klass);
9937                 /*
9938                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9939                 See mono/tests/array_load_exception.il
9940                 FIXME we should better report this error to the caller
9941                  */
9942                 if (!klass->methods)
9943                         return NULL;
9944                 for (i = 0; i < klass->method.count; ++i) {
9945                         MonoMethod *method = klass->methods [i];
9946
9947                         if (method->name[0] == name [0] && 
9948                                 !strcmp (name, method->name) &&
9949                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9950                                 ((method->flags & flags) == flags)) {
9951                                 res = method;
9952                                 break;
9953                         }
9954                 }
9955         }
9956         else {
9957             res = find_method_in_metadata (klass, name, param_count, flags);
9958         }
9959
9960         return res;
9961 }
9962
9963 /**
9964  * mono_class_set_failure:
9965  * @klass: class in which the failure was detected
9966  * @ex_type: the kind of exception/error to be thrown (later)
9967  * @ex_data: exception data (specific to each type of exception/error)
9968  *
9969  * Keep a detected failure informations in the class for later processing.
9970  * Note that only the first failure is kept.
9971  *
9972  * LOCKING: Acquires the loader lock.
9973  */
9974 gboolean
9975 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9976 {
9977         if (klass->exception_type)
9978                 return FALSE;
9979
9980         mono_loader_lock ();
9981         klass->exception_type = ex_type;
9982         if (ex_data)
9983                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9984         mono_loader_unlock ();
9985
9986         return TRUE;
9987 }
9988
9989 /*
9990  * mono_class_get_exception_data:
9991  *
9992  *   Return the exception_data property of KLASS.
9993  *
9994  * LOCKING: Acquires the loader lock.
9995  */
9996 gpointer
9997 mono_class_get_exception_data (MonoClass *klass)
9998 {
9999         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
10000 }
10001
10002 /**
10003  * mono_classes_init:
10004  *
10005  * Initialize the resources used by this module.
10006  */
10007 void
10008 mono_classes_init (void)
10009 {
10010         mono_os_mutex_init (&classes_mutex);
10011
10012         mono_counters_register ("Inflated methods size",
10013                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10014         mono_counters_register ("Inflated classes",
10015                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10016         mono_counters_register ("Inflated classes size",
10017                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10018         mono_counters_register ("MonoClass size",
10019                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10020         mono_counters_register ("MonoClassExt size",
10021                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10022 }
10023
10024 /**
10025  * mono_classes_cleanup:
10026  *
10027  * Free the resources used by this module.
10028  */
10029 void
10030 mono_classes_cleanup (void)
10031 {
10032         if (global_interface_bitset)
10033                 mono_bitset_free (global_interface_bitset);
10034         global_interface_bitset = NULL;
10035         mono_os_mutex_destroy (&classes_mutex);
10036 }
10037
10038 /**
10039  * mono_class_get_exception_for_failure:
10040  * @klass: class in which the failure was detected
10041  *
10042  * Return a constructed MonoException than the caller can then throw
10043  * using mono_raise_exception - or NULL if no failure is present (or
10044  * doesn't result in an exception).
10045  */
10046 MonoException*
10047 mono_class_get_exception_for_failure (MonoClass *klass)
10048 {
10049         gpointer exception_data = mono_class_get_exception_data (klass);
10050
10051         switch (klass->exception_type) {
10052         case MONO_EXCEPTION_TYPE_LOAD: {
10053                 MonoString *name;
10054                 MonoException *ex;
10055                 char *str = mono_type_get_full_name (klass);
10056                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10057                 name = mono_string_new (mono_domain_get (), str);
10058                 g_free (str);
10059                 ex = mono_get_exception_type_load (name, astr);
10060                 g_free (astr);
10061                 return ex;
10062         }
10063         case MONO_EXCEPTION_MISSING_METHOD: {
10064                 char *class_name = (char *)exception_data;
10065                 char *assembly_name = class_name + strlen (class_name) + 1;
10066
10067                 return mono_get_exception_missing_method (class_name, assembly_name);
10068         }
10069         case MONO_EXCEPTION_MISSING_FIELD: {
10070                 char *class_name = (char *)exception_data;
10071                 char *member_name = class_name + strlen (class_name) + 1;
10072
10073                 return mono_get_exception_missing_field (class_name, member_name);
10074         }
10075         case MONO_EXCEPTION_FILE_NOT_FOUND: {
10076                 char *msg_format = (char *)exception_data;
10077                 char *assembly_name = msg_format + strlen (msg_format) + 1;
10078                 char *msg = g_strdup_printf (msg_format, assembly_name);
10079                 MonoException *ex;
10080
10081                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10082
10083                 g_free (msg);
10084
10085                 return ex;
10086         }
10087         case MONO_EXCEPTION_BAD_IMAGE: {
10088                 return mono_get_exception_bad_image_format ((const char *)exception_data);
10089         }
10090         default: {
10091                 MonoLoaderError *error;
10092                 MonoException *ex;
10093                 
10094                 error = mono_loader_get_last_error ();
10095                 if (error != NULL){
10096                         ex = mono_loader_error_prepare_exception (error);
10097                         return ex;
10098                 }
10099                 
10100                 /* TODO - handle other class related failures */
10101                 return NULL;
10102         }
10103         }
10104 }
10105
10106 static gboolean
10107 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10108  {
10109         outer_klass = mono_class_get_generic_type_definition (outer_klass);
10110         inner_klass = mono_class_get_generic_type_definition (inner_klass);
10111         do {
10112                 if (outer_klass == inner_klass)
10113                         return TRUE;
10114                 inner_klass = inner_klass->nested_in;
10115         } while (inner_klass);
10116         return FALSE;
10117 }
10118
10119 MonoClass *
10120 mono_class_get_generic_type_definition (MonoClass *klass)
10121 {
10122         return klass->generic_class ? klass->generic_class->container_class : klass;
10123 }
10124
10125 /*
10126  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10127  * 
10128  * Generic instantiations are ignored for all super types of @klass.
10129  * 
10130  * Visibility checks ignoring generic instantiations.  
10131  */
10132 gboolean
10133 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10134 {
10135         int i;
10136         klass = mono_class_get_generic_type_definition (klass);
10137         parent = mono_class_get_generic_type_definition (parent);
10138         mono_class_setup_supertypes (klass);
10139
10140         for (i = 0; i < klass->idepth; ++i) {
10141                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10142                         return TRUE;
10143         }
10144         return FALSE;
10145 }
10146 /*
10147  * Subtype can only access parent members with family protection if the site object
10148  * is subclass of Subtype. For example:
10149  * class A { protected int x; }
10150  * class B : A {
10151  *      void valid_access () {
10152  *              B b;
10153  *              b.x = 0;
10154  *  }
10155  *  void invalid_access () {
10156  *              A a;
10157  *              a.x = 0;
10158  *  }
10159  * }
10160  * */
10161 static gboolean
10162 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10163 {
10164         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10165                 return FALSE;
10166
10167         if (context_klass == NULL)
10168                 return TRUE;
10169         /*if access_klass is not member_klass context_klass must be type compat*/
10170         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10171                 return FALSE;
10172         return TRUE;
10173 }
10174
10175 static gboolean
10176 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10177 {
10178         GSList *tmp;
10179         if (accessing == accessed)
10180                 return TRUE;
10181         if (!accessed || !accessing)
10182                 return FALSE;
10183
10184         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10185          * anywhere so untrusted friends are not safe to access platform's code internals */
10186         if (mono_security_core_clr_enabled ()) {
10187                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10188                         return FALSE;
10189         }
10190
10191         mono_assembly_load_friends (accessed);
10192         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10193                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10194                 /* Be conservative with checks */
10195                 if (!friend_->name)
10196                         continue;
10197                 if (strcmp (accessing->aname.name, friend_->name))
10198                         continue;
10199                 if (friend_->public_key_token [0]) {
10200                         if (!accessing->aname.public_key_token [0])
10201                                 continue;
10202                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10203                                 continue;
10204                 }
10205                 return TRUE;
10206         }
10207         return FALSE;
10208 }
10209
10210 /*
10211  * If klass is a generic type or if it is derived from a generic type, return the
10212  * MonoClass of the generic definition
10213  * Returns NULL if not found
10214  */
10215 static MonoClass*
10216 get_generic_definition_class (MonoClass *klass)
10217 {
10218         while (klass) {
10219                 if (klass->generic_class && klass->generic_class->container_class)
10220                         return klass->generic_class->container_class;
10221                 klass = klass->parent;
10222         }
10223         return NULL;
10224 }
10225
10226 static gboolean
10227 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10228 {
10229         int i;
10230         for (i = 0; i < ginst->type_argc; ++i) {
10231                 MonoType *type = ginst->type_argv[i];
10232                 switch (type->type) {
10233                 case MONO_TYPE_SZARRAY:
10234                         if (!can_access_type (access_klass, type->data.klass))
10235                                 return FALSE;
10236                         break;
10237                 case MONO_TYPE_ARRAY:
10238                         if (!can_access_type (access_klass, type->data.array->eklass))
10239                                 return FALSE;
10240                         break;
10241                 case MONO_TYPE_PTR:
10242                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10243                                 return FALSE;
10244                         break;
10245                 case MONO_TYPE_CLASS:
10246                 case MONO_TYPE_VALUETYPE:
10247                 case MONO_TYPE_GENERICINST:
10248                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10249                                 return FALSE;
10250                 default:
10251                         break;
10252                 }
10253         }
10254         return TRUE;
10255 }
10256
10257 static gboolean
10258 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10259 {
10260         int access_level;
10261
10262         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10263                 return TRUE;
10264
10265         if (access_klass->element_class && !access_klass->enumtype)
10266                 access_klass = access_klass->element_class;
10267
10268         if (member_klass->element_class && !member_klass->enumtype)
10269                 member_klass = member_klass->element_class;
10270
10271         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10272
10273         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10274                 return TRUE;
10275
10276         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10277                 return FALSE;
10278
10279         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10280                 return TRUE;
10281
10282         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10283                 return FALSE;
10284
10285         /*Non nested type with nested visibility. We just fail it.*/
10286         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10287                 return FALSE;
10288
10289         switch (access_level) {
10290         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10291                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10292
10293         case TYPE_ATTRIBUTE_PUBLIC:
10294                 return TRUE;
10295
10296         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10297                 return TRUE;
10298
10299         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10300                 return is_nesting_type (member_klass, access_klass);
10301
10302         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10303                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10304
10305         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10306                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10307
10308         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10309                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10310                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10311
10312         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10313                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10314                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10315         }
10316         return FALSE;
10317 }
10318
10319 /* FIXME: check visibility of type, too */
10320 static gboolean
10321 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10322 {
10323         MonoClass *member_generic_def;
10324         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10325                 return TRUE;
10326
10327         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10328                                         access_klass->generic_container) && 
10329                         (member_generic_def = get_generic_definition_class (member_klass))) {
10330                 MonoClass *access_container;
10331
10332                 if (access_klass->generic_container)
10333                         access_container = access_klass;
10334                 else
10335                         access_container = access_klass->generic_class->container_class;
10336
10337                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10338                         return TRUE;
10339         }
10340
10341         /* Partition I 8.5.3.2 */
10342         /* the access level values are the same for fields and methods */
10343         switch (access_level) {
10344         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10345                 /* same compilation unit */
10346                 return access_klass->image == member_klass->image;
10347         case FIELD_ATTRIBUTE_PRIVATE:
10348                 return access_klass == member_klass;
10349         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10350                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10351                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10352                         return TRUE;
10353                 return FALSE;
10354         case FIELD_ATTRIBUTE_ASSEMBLY:
10355                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10356         case FIELD_ATTRIBUTE_FAMILY:
10357                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10358                         return TRUE;
10359                 return FALSE;
10360         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10361                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10362                         return TRUE;
10363                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10364         case FIELD_ATTRIBUTE_PUBLIC:
10365                 return TRUE;
10366         }
10367         return FALSE;
10368 }
10369
10370 /**
10371  * mono_method_can_access_field:
10372  * @method: Method that will attempt to access the field
10373  * @field: the field to access
10374  *
10375  * Used to determine if a method is allowed to access the specified field.
10376  *
10377  * Returns: TRUE if the given @method is allowed to access the @field while following
10378  * the accessibility rules of the CLI.
10379  */
10380 gboolean
10381 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10382 {
10383         /* FIXME: check all overlapping fields */
10384         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10385         if (!can) {
10386                 MonoClass *nested = method->klass->nested_in;
10387                 while (nested) {
10388                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10389                         if (can)
10390                                 return TRUE;
10391                         nested = nested->nested_in;
10392                 }
10393         }
10394         return can;
10395 }
10396
10397 /**
10398  * mono_method_can_access_method:
10399  * @method: Method that will attempt to access the other method
10400  * @called: the method that we want to probe for accessibility.
10401  *
10402  * Used to determine if the @method is allowed to access the specified @called method.
10403  *
10404  * Returns: TRUE if the given @method is allowed to invoke the @called while following
10405  * the accessibility rules of the CLI.
10406  */
10407 gboolean
10408 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10409 {
10410         int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10411         if (!can) {
10412                 MonoClass *nested = method->klass->nested_in;
10413                 while (nested) {
10414                         can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10415                         if (can)
10416                                 return TRUE;
10417                         nested = nested->nested_in;
10418                 }
10419         }
10420         /* 
10421          * FIXME:
10422          * with generics calls to explicit interface implementations can be expressed
10423          * directly: the method is private, but we must allow it. This may be opening
10424          * a hole or the generics code should handle this differently.
10425          * Maybe just ensure the interface type is public.
10426          */
10427         if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10428                 return TRUE;
10429         return can;
10430 }
10431
10432 /*
10433  * mono_method_can_access_method_full:
10434  * @method: The caller method 
10435  * @called: The called method 
10436  * @context_klass: The static type on stack of the owner @called object used
10437  * 
10438  * This function must be used with instance calls, as they have more strict family accessibility.
10439  * It can be used with static methods, but context_klass should be NULL.
10440  * 
10441  * Returns: TRUE if caller have proper visibility and acessibility to @called
10442  */
10443 gboolean
10444 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10445 {
10446         MonoClass *access_class = method->klass;
10447         MonoClass *member_class = called->klass;
10448         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10449         if (!can) {
10450                 MonoClass *nested = access_class->nested_in;
10451                 while (nested) {
10452                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10453                         if (can)
10454                                 break;
10455                         nested = nested->nested_in;
10456                 }
10457         }
10458
10459         if (!can)
10460                 return FALSE;
10461
10462         can = can_access_type (access_class, member_class);
10463         if (!can) {
10464                 MonoClass *nested = access_class->nested_in;
10465                 while (nested) {
10466                         can = can_access_type (nested, member_class);
10467                         if (can)
10468                                 break;
10469                         nested = nested->nested_in;
10470                 }
10471         }
10472
10473         if (!can)
10474                 return FALSE;
10475
10476         if (called->is_inflated) {
10477                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10478                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10479                         return FALSE;
10480         }
10481                 
10482         return TRUE;
10483 }
10484
10485
10486 /*
10487  * mono_method_can_access_field_full:
10488  * @method: The caller method 
10489  * @field: The accessed field
10490  * @context_klass: The static type on stack of the owner @field object used
10491  * 
10492  * This function must be used with instance fields, as they have more strict family accessibility.
10493  * It can be used with static fields, but context_klass should be NULL.
10494  * 
10495  * Returns: TRUE if caller have proper visibility and acessibility to @field
10496  */
10497 gboolean
10498 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10499 {
10500         MonoClass *access_class = method->klass;
10501         MonoClass *member_class = field->parent;
10502         /* FIXME: check all overlapping fields */
10503         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10504         if (!can) {
10505                 MonoClass *nested = access_class->nested_in;
10506                 while (nested) {
10507                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10508                         if (can)
10509                                 break;
10510                         nested = nested->nested_in;
10511                 }
10512         }
10513
10514         if (!can)
10515                 return FALSE;
10516
10517         can = can_access_type (access_class, member_class);
10518         if (!can) {
10519                 MonoClass *nested = access_class->nested_in;
10520                 while (nested) {
10521                         can = can_access_type (nested, member_class);
10522                         if (can)
10523                                 break;
10524                         nested = nested->nested_in;
10525                 }
10526         }
10527
10528         if (!can)
10529                 return FALSE;
10530         return TRUE;
10531 }
10532
10533 /*
10534  * mono_class_can_access_class:
10535  * @source_class: The source class 
10536  * @target_class: The accessed class
10537  * 
10538  * This function returns is @target_class is visible to @source_class
10539  * 
10540  * Returns: TRUE if source have proper visibility and acessibility to target
10541  */
10542 gboolean
10543 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10544 {
10545         return can_access_type (source_class, target_class);
10546 }
10547
10548 /**
10549  * mono_type_is_valid_enum_basetype:
10550  * @type: The MonoType to check
10551  *
10552  * Returns: TRUE if the type can be used as the basetype of an enum
10553  */
10554 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10555         switch (type->type) {
10556         case MONO_TYPE_I1:
10557         case MONO_TYPE_U1:
10558         case MONO_TYPE_BOOLEAN:
10559         case MONO_TYPE_I2:
10560         case MONO_TYPE_U2:
10561         case MONO_TYPE_CHAR:
10562         case MONO_TYPE_I4:
10563         case MONO_TYPE_U4:
10564         case MONO_TYPE_I8:
10565         case MONO_TYPE_U8:
10566         case MONO_TYPE_I:
10567         case MONO_TYPE_U:
10568                 return TRUE;
10569         default:
10570                 return FALSE;
10571         }
10572 }
10573
10574 /**
10575  * mono_class_is_valid_enum:
10576  * @klass: An enum class to be validated
10577  *
10578  * This method verify the required properties an enum should have.
10579  *  
10580  * Returns: TRUE if the informed enum class is valid 
10581  *
10582  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10583  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10584  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10585  */
10586 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10587         MonoClassField * field;
10588         gpointer iter = NULL;
10589         gboolean found_base_field = FALSE;
10590
10591         g_assert (klass->enumtype);
10592         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10593         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10594                 return FALSE;
10595         }
10596
10597         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10598                 return FALSE;
10599
10600         while ((field = mono_class_get_fields (klass, &iter))) {
10601                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10602                         if (found_base_field)
10603                                 return FALSE;
10604                         found_base_field = TRUE;
10605                         if (!mono_type_is_valid_enum_basetype (field->type))
10606                                 return FALSE;
10607                 }
10608         }
10609
10610         if (!found_base_field)
10611                 return FALSE;
10612
10613         if (klass->method.count > 0) 
10614                 return FALSE;
10615
10616         return TRUE;
10617 }
10618
10619 gboolean
10620 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10621 {
10622         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10623 }
10624
10625 /*
10626  * mono_class_setup_interface_id:
10627  *
10628  * Initializes MonoClass::interface_id if required.
10629  *
10630  * LOCKING: Acquires the loader lock.
10631  */
10632 void
10633 mono_class_setup_interface_id (MonoClass *klass)
10634 {
10635         mono_loader_lock ();
10636         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10637                 klass->interface_id = mono_get_unique_iid (klass);
10638         mono_loader_unlock ();
10639 }
10640
10641 /*
10642  * mono_class_alloc_ext:
10643  *
10644  *   Allocate klass->ext if not already done.
10645  */
10646 void
10647 mono_class_alloc_ext (MonoClass *klass)
10648 {
10649         MonoClassExt *ext;
10650
10651         if (klass->ext)
10652                 return;
10653
10654         ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10655         mono_image_lock (klass->image);
10656         mono_memory_barrier ();
10657         if (!klass->ext)
10658                 klass->ext = ext;
10659         class_ext_size += sizeof (MonoClassExt);
10660         mono_image_unlock (klass->image);
10661 }
10662
10663 /*
10664  * mono_class_setup_interfaces:
10665  *
10666  *   Initialize klass->interfaces/interfaces_count.
10667  * LOCKING: Acquires the loader lock.
10668  * This function can fail the type.
10669  */
10670 void
10671 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10672 {
10673         int i, interface_count;
10674         MonoClass **interfaces;
10675
10676         mono_error_init (error);
10677
10678         if (klass->interfaces_inited)
10679                 return;
10680
10681         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10682                 MonoType *args [1];
10683
10684                 /* generic IList, ICollection, IEnumerable */
10685                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10686                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10687
10688                 args [0] = &klass->element_class->byval_arg;
10689                 interfaces [0] = mono_class_bind_generic_parameters (
10690                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10691                 if (interface_count > 1)
10692                         interfaces [1] = mono_class_bind_generic_parameters (
10693                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10694         } else if (klass->generic_class) {
10695                 MonoClass *gklass = klass->generic_class->container_class;
10696
10697                 mono_class_setup_interfaces (gklass, error);
10698                 if (!mono_error_ok (error)) {
10699                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10700                         return;
10701                 }
10702
10703                 interface_count = gklass->interface_count;
10704                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10705                 for (i = 0; i < interface_count; i++) {
10706                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10707                         if (!mono_error_ok (error)) {
10708                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10709                                 return;
10710                         }
10711                 }
10712         } else {
10713                 interface_count = 0;
10714                 interfaces = NULL;
10715         }
10716
10717         mono_image_lock (klass->image);
10718
10719         if (!klass->interfaces_inited) {
10720                 klass->interface_count = interface_count;
10721                 klass->interfaces = interfaces;
10722
10723                 mono_memory_barrier ();
10724
10725                 klass->interfaces_inited = TRUE;
10726         }
10727
10728         mono_image_unlock (klass->image);
10729 }
10730
10731 static void
10732 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10733 {
10734         MonoClass *klass = field->parent;
10735         MonoImage *image = klass->image;
10736         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10737         int field_idx = field - klass->fields;
10738
10739         mono_error_init (error);
10740
10741         if (gtd) {
10742                 MonoClassField *gfield = &gtd->fields [field_idx];
10743                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10744                 if (!mono_error_ok (error)) {
10745                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10746                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10747                 }
10748
10749                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10750                 if (!mono_error_ok (error)) {
10751                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10752                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10753                 }
10754         } else {
10755                 const char *sig;
10756                 guint32 cols [MONO_FIELD_SIZE];
10757                 MonoGenericContainer *container = NULL;
10758                 int idx = klass->field.first + field_idx;
10759
10760                 /*FIXME, in theory we do not lazy load SRE fields*/
10761                 g_assert (!image_is_dynamic (image));
10762
10763                 if (klass->generic_container) {
10764                         container = klass->generic_container;
10765                 } else if (gtd) {
10766                         container = gtd->generic_container;
10767                         g_assert (container);
10768                 }
10769
10770                 /* klass->field.first and idx points into the fieldptr table */
10771                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10772
10773                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10774                         mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10775                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10776                         return;
10777                 }
10778
10779                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10780
10781                 mono_metadata_decode_value (sig, &sig);
10782                 /* FIELD signature == 0x06 */
10783                 g_assert (*sig == 0x06);
10784
10785                 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10786                 if (!field->type) {
10787                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10788                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10789                 }
10790         }
10791 }
10792
10793 static guint32
10794 mono_field_resolve_flags (MonoClassField *field)
10795 {
10796         MonoClass *klass = field->parent;
10797         MonoImage *image = klass->image;
10798         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10799         int field_idx = field - klass->fields;
10800
10801
10802         if (gtd) {
10803                 MonoClassField *gfield = &gtd->fields [field_idx];
10804                 return mono_field_get_flags (gfield);
10805         } else {
10806                 int idx = klass->field.first + field_idx;
10807
10808                 /*FIXME, in theory we do not lazy load SRE fields*/
10809                 g_assert (!image_is_dynamic (image));
10810
10811                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10812         }
10813 }
10814
10815 /**
10816  * mono_class_setup_basic_field_info:
10817  * @class: The class to initialize
10818  *
10819  * Initializes the klass->fields array of fields.
10820  * Aquires the loader lock.
10821  */
10822 static void
10823 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10824 {
10825         mono_loader_lock ();
10826         mono_class_setup_basic_field_info (klass);
10827         mono_loader_unlock ();
10828 }
10829
10830 /**
10831  * mono_class_get_fields_lazy:
10832  * @klass: the MonoClass to act on
10833  *
10834  * This routine is an iterator routine for retrieving the fields in a class.
10835  * Only minimal information about fields are loaded. Accessors must be used
10836  * for all MonoClassField returned.
10837  *
10838  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10839  * iterate over all of the elements.  When no more values are
10840  * available, the return value is NULL.
10841  *
10842  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10843  */
10844 MonoClassField*
10845 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10846 {
10847         MonoClassField* field;
10848         if (!iter)
10849                 return NULL;
10850         if (!*iter) {
10851                 mono_class_setup_basic_field_info_locking (klass);
10852                 if (!klass->fields)
10853                         return NULL;
10854                 /* start from the first */
10855                 if (klass->field.count) {
10856                         *iter = &klass->fields [0];
10857                         return (MonoClassField *)*iter;
10858                 } else {
10859                         /* no fields */
10860                         return NULL;
10861                 }
10862         }
10863         field = (MonoClassField *)*iter;
10864         field++;
10865         if (field < &klass->fields [klass->field.count]) {
10866                 *iter = field;
10867                 return (MonoClassField *)*iter;
10868         }
10869         return NULL;
10870 }
10871
10872 char*
10873 mono_class_full_name (MonoClass *klass)
10874 {
10875         return mono_type_full_name (&klass->byval_arg);
10876 }
10877
10878 /* Declare all shared lazy type lookup functions */
10879 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)