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