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