6218589a88e3c47b96ecacfff2701e05e5035e7a
[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                 }
5597
5598                 klass->parent = parent;
5599
5600                 if (parent->generic_class && !parent->name) {
5601                         /*
5602                          * If the parent is a generic instance, we may get
5603                          * called before it is fully initialized, especially
5604                          * before it has its name.
5605                          */
5606                         return;
5607                 }
5608
5609 #ifndef DISABLE_REMOTING
5610                 klass->marshalbyref = parent->marshalbyref;
5611                 klass->contextbound  = parent->contextbound;
5612 #endif
5613
5614                 klass->delegate  = parent->delegate;
5615
5616                 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5617                         mono_class_set_is_com_object (klass);
5618                 
5619                 if (system_namespace) {
5620 #ifndef DISABLE_REMOTING
5621                         if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5622                                 klass->marshalbyref = 1;
5623
5624                         if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject")) 
5625                                 klass->contextbound  = 1;
5626 #endif
5627                         if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) 
5628                                 klass->delegate  = 1;
5629                 }
5630
5631                 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && 
5632                                                 (strcmp (klass->parent->name_space, "System") == 0)))
5633                         klass->valuetype = 1;
5634                 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5635                         klass->valuetype = klass->enumtype = 1;
5636                 }
5637                 /*klass->enumtype = klass->parent->enumtype; */
5638         } else {
5639                 /* initialize com types if COM interfaces are present */
5640 #ifndef DISABLE_COM
5641                 if (MONO_CLASS_IS_IMPORT (klass))
5642                         init_com_from_comimport (klass);
5643 #endif
5644                 klass->parent = NULL;
5645         }
5646
5647 }
5648
5649 /*
5650  * mono_class_setup_supertypes:
5651  * @class: a class
5652  *
5653  * Build the data structure needed to make fast type checks work.
5654  * This currently sets two fields in @class:
5655  *  - idepth: distance between @class and System.Object in the type
5656  *    hierarchy + 1
5657  *  - supertypes: array of classes: each element has a class in the hierarchy
5658  *    starting from @class up to System.Object
5659  * 
5660  * LOCKING: This function is atomic, in case of contention we waste memory.
5661  */
5662 void
5663 mono_class_setup_supertypes (MonoClass *klass)
5664 {
5665         int ms;
5666         MonoClass **supertypes;
5667
5668         mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5669         if (supertypes)
5670                 return;
5671
5672         if (klass->parent && !klass->parent->supertypes)
5673                 mono_class_setup_supertypes (klass->parent);
5674         if (klass->parent)
5675                 klass->idepth = klass->parent->idepth + 1;
5676         else
5677                 klass->idepth = 1;
5678
5679         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, klass->idepth);
5680         supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5681
5682         if (klass->parent) {
5683                 CHECKED_METADATA_WRITE_PTR ( supertypes [klass->idepth - 1] , klass );
5684
5685                 int supertype_idx;
5686                 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5687                         CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5688         } else {
5689                 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5690         }
5691
5692         CHECKED_METADATA_WRITE_PTR_ATOMIC ( klass->supertypes , supertypes );
5693 }
5694
5695 static gboolean
5696 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5697 {
5698         MonoClass *gtd = (MonoClass*)user_data;
5699         /* Only try to fix generic instances of @gtd */
5700         if (gclass->generic_class->container_class != gtd)
5701                 return FALSE;
5702
5703         /* Check if the generic instance has no parent. */
5704         if (gtd->parent && !gclass->parent)
5705                 mono_generic_class_setup_parent (gclass, gtd);
5706
5707         return TRUE;
5708 }
5709
5710 static void
5711 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5712 {
5713         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (msg));
5714         mono_error_set_type_load_class (error, klass, msg);
5715 }
5716
5717 /**
5718  * mono_class_create_from_typedef:
5719  * @image: image where the token is valid
5720  * @type_token:  typedef token
5721  * @error:  used to return any error found while creating the type
5722  *
5723  * Create the MonoClass* representing the specified type token.
5724  * @type_token must be a TypeDef token.
5725  *
5726  * FIXME: don't return NULL on failure, just the the caller figure it out.
5727  */
5728 static MonoClass *
5729 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5730 {
5731         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5732         MonoClass *klass, *parent = NULL;
5733         guint32 cols [MONO_TYPEDEF_SIZE];
5734         guint32 cols_next [MONO_TYPEDEF_SIZE];
5735         guint tidx = mono_metadata_token_index (type_token);
5736         MonoGenericContext *context = NULL;
5737         const char *name, *nspace;
5738         guint icount = 0; 
5739         MonoClass **interfaces;
5740         guint32 field_last, method_last;
5741         guint32 nesting_tokeen;
5742
5743         mono_error_init (error);
5744
5745         if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5746                 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5747                 return NULL;
5748         }
5749
5750         mono_loader_lock ();
5751
5752         if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5753                 mono_loader_unlock ();
5754                 return klass;
5755         }
5756
5757         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5758         
5759         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5760         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5761
5762         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
5763
5764         klass->name = name;
5765         klass->name_space = nspace;
5766
5767         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5768
5769         klass->image = image;
5770         klass->type_token = type_token;
5771         klass->flags = cols [MONO_TYPEDEF_FLAGS];
5772
5773         mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5774
5775         classes_size += sizeof (MonoClass);
5776
5777         /*
5778          * Check whether we're a generic type definition.
5779          */
5780         klass->generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5781         if (klass->generic_container) {
5782                 klass->is_generic = 1;
5783                 klass->generic_container->owner.klass = klass;
5784                 klass->generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5785                 context = &klass->generic_container->context;
5786         }
5787
5788         if (klass->generic_container)
5789                 enable_gclass_recording ();
5790
5791         if (cols [MONO_TYPEDEF_EXTENDS]) {
5792                 MonoClass *tmp;
5793                 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5794
5795                 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5796                         /*WARNING: this must satisfy mono_metadata_type_hash*/
5797                         klass->this_arg.byref = 1;
5798                         klass->this_arg.data.klass = klass;
5799                         klass->this_arg.type = MONO_TYPE_CLASS;
5800                         klass->byval_arg.data.klass = klass;
5801                         klass->byval_arg.type = MONO_TYPE_CLASS;
5802                 }
5803                 parent = mono_class_get_checked (image, parent_token, error);
5804                 if (parent && context) /* Always inflate */
5805                         parent = mono_class_inflate_generic_class_checked (parent, context, error);
5806
5807                 if (parent == NULL) {
5808                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5809                         goto parent_failure;
5810                 }
5811
5812                 for (tmp = parent; tmp; tmp = tmp->parent) {
5813                         if (tmp == klass) {
5814                                 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5815                                 goto parent_failure;
5816                         }
5817                         if (klass->generic_container && tmp->generic_class && tmp->generic_class->container_class == klass) {
5818                                 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5819                                 goto parent_failure;
5820                         }
5821                 }
5822         }
5823
5824         mono_class_setup_parent (klass, parent);
5825
5826         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5827         mono_class_setup_mono_type (klass);
5828
5829         if (klass->generic_container)
5830                 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5831
5832         /* 
5833          * This might access klass->byval_arg for recursion generated by generic constraints,
5834          * so it has to come after setup_mono_type ().
5835          */
5836         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5837                 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5838                 if (!mono_error_ok (error)) {
5839                         /*FIXME implement a mono_class_set_failure_from_mono_error */
5840                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5841                         mono_loader_unlock ();
5842                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5843                         return NULL;
5844                 }
5845         }
5846
5847         if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5848                 klass->unicode = 1;
5849
5850 #ifdef HOST_WIN32
5851         if ((klass->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5852                 klass->unicode = 1;
5853 #endif
5854
5855         klass->cast_class = klass->element_class = klass;
5856
5857         if (!klass->enumtype) {
5858                 if (!mono_metadata_interfaces_from_typedef_full (
5859                             image, type_token, &interfaces, &icount, FALSE, context, error)){
5860
5861                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5862                         mono_loader_unlock ();
5863                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5864                         return NULL;
5865                 }
5866
5867                 klass->interfaces = interfaces;
5868                 klass->interface_count = icount;
5869                 klass->interfaces_inited = 1;
5870         }
5871
5872         /*g_print ("Load class %s\n", name);*/
5873
5874         /*
5875          * Compute the field and method lists
5876          */
5877         klass->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5878         klass->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5879
5880         if (tt->rows > tidx){           
5881                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5882                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5883                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5884         } else {
5885                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
5886                 method_last = image->tables [MONO_TABLE_METHOD].rows;
5887         }
5888
5889         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
5890             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5891                 klass->field.count = field_last - klass->field.first;
5892         else
5893                 klass->field.count = 0;
5894
5895         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5896                 klass->method.count = method_last - klass->method.first;
5897         else
5898                 klass->method.count = 0;
5899
5900         /* reserve space to store vector pointer in arrays */
5901         if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5902                 klass->instance_size += 2 * sizeof (gpointer);
5903                 g_assert (klass->field.count == 0);
5904         }
5905
5906         if (klass->enumtype) {
5907                 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5908                 if (!enum_basetype) {
5909                         /*set it to a default value as the whole runtime can't handle this to be null*/
5910                         klass->cast_class = klass->element_class = mono_defaults.int32_class;
5911                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
5912                         mono_loader_unlock ();
5913                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5914                         return NULL;
5915                 }
5916                 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5917         }
5918
5919         /*
5920          * If we're a generic type definition, load the constraints.
5921          * We must do this after the class has been constructed to make certain recursive scenarios
5922          * work.
5923          */
5924         if (klass->generic_container && !mono_metadata_load_generic_param_constraints_checked (image, type_token, klass->generic_container, error)) {
5925                 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)));
5926                 mono_loader_unlock ();
5927                 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5928                 return NULL;
5929         }
5930
5931         if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5932                 if (!strncmp (name, "Vector", 6))
5933                         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");
5934         }
5935
5936         mono_loader_unlock ();
5937
5938         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5939
5940         return klass;
5941
5942 parent_failure:
5943         mono_class_setup_mono_type (klass);
5944         mono_loader_unlock ();
5945         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5946         return NULL;
5947 }
5948
5949 /** Is klass a Nullable<T> ginst? */
5950 gboolean
5951 mono_class_is_nullable (MonoClass *klass)
5952 {
5953        return klass->generic_class != NULL &&
5954                klass->generic_class->container_class == mono_defaults.generic_nullable_class;
5955 }
5956
5957
5958 /** if klass is T? return T */
5959 MonoClass*
5960 mono_class_get_nullable_param (MonoClass *klass)
5961 {
5962        g_assert (mono_class_is_nullable (klass));
5963        return mono_class_from_mono_type (klass->generic_class->context.class_inst->type_argv [0]);
5964 }
5965
5966 static void
5967 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5968 {
5969         if (gtd->parent) {
5970                 MonoError error;
5971                 MonoGenericClass *gclass = klass->generic_class;
5972
5973                 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5974                 if (!mono_error_ok (&error)) {
5975                         /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5976                         klass->parent = mono_defaults.object_class;
5977                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
5978                         mono_error_cleanup (&error);
5979                 }
5980         }
5981         if (klass->parent)
5982                 mono_class_setup_parent (klass, klass->parent);
5983
5984         if (klass->enumtype) {
5985                 klass->cast_class = gtd->cast_class;
5986                 klass->element_class = gtd->element_class;
5987         }
5988 }
5989
5990
5991 /*
5992  * Create the `MonoClass' for an instantiation of a generic type.
5993  * We only do this if we actually need it.
5994  */
5995 MonoClass*
5996 mono_generic_class_get_class (MonoGenericClass *gclass)
5997 {
5998         MonoClass *klass, *gklass;
5999
6000         if (gclass->cached_class)
6001                 return gclass->cached_class;
6002
6003         mono_loader_lock ();
6004         if (gclass->cached_class) {
6005                 mono_loader_unlock ();
6006                 return gclass->cached_class;
6007         }
6008
6009         klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClass));
6010
6011         gklass = gclass->container_class;
6012
6013         if (record_gclass_instantiation > 0)
6014                 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
6015
6016         if (gklass->nested_in) {
6017                 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
6018                 klass->nested_in = gklass->nested_in;
6019         }
6020
6021         klass->name = gklass->name;
6022         klass->name_space = gklass->name_space;
6023         
6024         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6025         
6026         klass->image = gklass->image;
6027         klass->flags = gklass->flags;
6028         klass->type_token = gklass->type_token;
6029         klass->field.count = gklass->field.count;
6030
6031         klass->is_inflated = 1;
6032         klass->generic_class = gclass;
6033
6034         klass->byval_arg.type = MONO_TYPE_GENERICINST;
6035         klass->this_arg.type = klass->byval_arg.type;
6036         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
6037         klass->this_arg.byref = TRUE;
6038         klass->enumtype = gklass->enumtype;
6039         klass->valuetype = gklass->valuetype;
6040
6041         klass->cast_class = klass->element_class = klass;
6042
6043         if (mono_class_is_nullable (klass))
6044                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
6045
6046         /*
6047          * We're not interested in the nested classes of a generic instance.
6048          * We use the generic type definition to look for nested classes.
6049          */
6050
6051         mono_generic_class_setup_parent (klass, gklass);
6052
6053         if (gclass->is_dynamic) {
6054                 /*
6055                  * 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.
6056                  * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
6057                  * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
6058                 */
6059                 if (!gklass->wastypebuilder)
6060                         klass->inited = 1;
6061
6062                 mono_class_setup_supertypes (klass);
6063
6064                 if (klass->enumtype) {
6065                         /*
6066                          * For enums, gklass->fields might not been set, but instance_size etc. is 
6067                          * already set in mono_reflection_create_internal_class (). For non-enums,
6068                          * these will be computed normally in mono_class_layout_fields ().
6069                          */
6070                         klass->instance_size = gklass->instance_size;
6071                         klass->sizes.class_size = gklass->sizes.class_size;
6072                         mono_memory_barrier ();
6073                         klass->size_inited = 1;
6074                 }
6075         }
6076
6077         mono_memory_barrier ();
6078         gclass->cached_class = klass;
6079
6080         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6081
6082         inflated_classes ++;
6083         inflated_classes_size += sizeof (MonoClass);
6084         
6085         mono_loader_unlock ();
6086
6087         return klass;
6088 }
6089
6090 static MonoImage *
6091 get_image_for_container (MonoGenericContainer *container)
6092 {
6093         MonoImage *result;
6094         if (container->is_anonymous) {
6095                 result = container->owner.image;
6096         } else {
6097                 MonoClass *klass;
6098                 if (container->is_method) {
6099                         MonoMethod *method = container->owner.method;
6100                         g_assert_checked (method);
6101                         klass = method->klass;
6102                 } else {
6103                         klass = container->owner.klass;
6104                 }
6105                 g_assert_checked (klass);
6106                 result = klass->image;
6107         }
6108         g_assert (result);
6109         return result;
6110 }
6111
6112 MonoImage *
6113 get_image_for_generic_param (MonoGenericParam *param)
6114 {
6115         MonoGenericContainer *container = mono_generic_param_owner (param);
6116         g_assert_checked (container);
6117         return get_image_for_container (container);
6118 }
6119
6120 // Make a string in the designated image consisting of a single integer.
6121 #define INT_STRING_SIZE 16
6122 char *
6123 make_generic_name_string (MonoImage *image, int num)
6124 {
6125         char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
6126         g_snprintf (name, INT_STRING_SIZE, "%d", num);
6127         return name;
6128 }
6129
6130 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
6131 // pinfo is derived from param by the caller for us.
6132 static MonoClass*
6133 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
6134 {
6135         MonoClass *klass, **ptr;
6136         int count, pos, i;
6137         MonoGenericContainer *container = mono_generic_param_owner (param);
6138         g_assert_checked (container);
6139
6140         MonoImage *image = get_image_for_container (container);
6141         gboolean is_mvar = container->is_method;
6142         gboolean is_anonymous = container->is_anonymous;
6143
6144         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6145         classes_size += sizeof (MonoClass);
6146
6147         if (pinfo) {
6148                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
6149         } else {
6150                 int n = mono_generic_param_num (param);
6151                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
6152         }
6153
6154         if (is_anonymous) {
6155                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space ,  "" );
6156         } else if (is_mvar) {
6157                 MonoMethod *omethod = container->owner.method;
6158                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6159         } else {
6160                 MonoClass *oklass = container->owner.klass;
6161                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6162         }
6163
6164         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6165
6166         // Count non-NULL items in pinfo->constraints
6167         count = 0;
6168         if (pinfo)
6169                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6170                         ;
6171
6172         pos = 0;
6173         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6174                 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6175                 pos++;
6176         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6177                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6178         } else {
6179                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6180         }
6181
6182         if (count - pos > 0) {
6183                 klass->interface_count = count - pos;
6184                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6185                 klass->interfaces_inited = TRUE;
6186                 for (i = pos; i < count; i++)
6187                         CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6188         }
6189
6190         CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6191
6192         klass->inited = TRUE;
6193         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class ,    klass );
6194         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6195         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
6196
6197         klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6198         klass->this_arg.type = klass->byval_arg.type;
6199         CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param ,  param );
6200         CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6201         klass->this_arg.byref = TRUE;
6202
6203         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6204         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6205
6206         /*Init these fields to sane values*/
6207         klass->min_align = 1;
6208         /*
6209          * This makes sure the the value size of this class is equal to the size of the types the gparam is
6210          * constrained to, the JIT depends on this.
6211          */
6212         klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6213         mono_memory_barrier ();
6214         klass->size_inited = 1;
6215         klass->setup_fields_called = 1;
6216
6217         mono_class_setup_supertypes (klass);
6218
6219         if (count - pos > 0) {
6220                 mono_class_setup_vtable (klass->parent);
6221                 if (mono_class_has_failure (klass->parent))
6222                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Failed to setup parent interfaces"));
6223                 else
6224                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6225         }
6226
6227         return klass;
6228 }
6229
6230 #define FAST_CACHE_SIZE 16
6231
6232 /*
6233  * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6234  * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6235  * we cache the MonoClasses.
6236  * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6237  * LOCKING: Takes the image lock depending on @take_lock.
6238  */
6239 static MonoClass *
6240 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6241 {
6242         int n = mono_generic_param_num (param);
6243         MonoImage *image = get_image_for_generic_param (param);
6244         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6245         MonoClass *klass = NULL;
6246         GHashTable *ht;
6247
6248         g_assert (image);
6249
6250         // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6251         // For high numbers or constraints we have to use pointer hashes.
6252         if (param->gshared_constraint) {
6253                 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6254                 if (ht) {
6255                         if (take_lock)
6256                                 mono_image_lock (image);
6257                         klass = (MonoClass *)g_hash_table_lookup (ht, param);
6258                         if (take_lock)
6259                                 mono_image_unlock (image);
6260                 }
6261                 return klass;
6262         }
6263
6264         if (n < FAST_CACHE_SIZE) {
6265                 if (is_mvar)
6266                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6267                 else
6268                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6269         } else {
6270                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6271                 if (ht) {
6272                         if (take_lock)
6273                                 mono_image_lock (image);
6274                         klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6275                         if (take_lock)
6276                                 mono_image_unlock (image);
6277                 }
6278                 return klass;
6279         }
6280 }
6281
6282 /*
6283  * LOCKING: Image lock (param->image) must be held
6284  */
6285 static void
6286 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6287 {
6288         int n = mono_generic_param_num (param);
6289         MonoImage *image = get_image_for_generic_param (param);
6290         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6291
6292         g_assert (image);
6293
6294         if (param->gshared_constraint) {
6295                 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6296                 if (!ht) {
6297                         ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6298                         mono_memory_barrier ();
6299                         if (is_mvar)
6300                                 image->mvar_cache_constrained = ht;
6301                         else
6302                                 image->var_cache_constrained = ht;
6303                 }
6304                 g_hash_table_insert (ht, param, klass);
6305         } else if (n < FAST_CACHE_SIZE) {
6306                 if (is_mvar) {
6307                         /* Requires locking to avoid droping an already published class */
6308                         if (!image->mvar_cache_fast)
6309                                 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6310                         image->mvar_cache_fast [n] = klass;
6311                 } else {
6312                         if (!image->var_cache_fast)
6313                                 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6314                         image->var_cache_fast [n] = klass;
6315                 }
6316         } else {
6317                 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6318                 if (!ht) {
6319                         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6320                         if (!ht) {
6321                                 ht = g_hash_table_new (NULL, NULL);
6322                                 mono_memory_barrier ();
6323                                 if (is_mvar)
6324                                         image->mvar_cache_slow = ht;
6325                                 else
6326                                         image->var_cache_slow = ht;
6327                         }
6328                 }
6329                 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6330         }
6331 }
6332
6333 /*
6334  * LOCKING: Acquires the image lock (@image).
6335  */
6336 MonoClass *
6337 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6338 {
6339         MonoImage *image = get_image_for_generic_param (param);
6340         MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6341         MonoClass *klass, *klass2;
6342
6343         // If a klass already exists for this object and is cached, return it.
6344         if (pinfo) // Non-anonymous
6345                 klass = pinfo->pklass;
6346         else     // Anonymous
6347                 klass = get_anon_gparam_class (param, TRUE);
6348
6349         if (klass)
6350                 return klass;
6351
6352         // Create a new klass
6353         klass = make_generic_param_class (param, pinfo);
6354
6355         // Now we need to cache the klass we created.
6356         // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6357         // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6358         // and allow our newly-created klass object to just leak.
6359         mono_memory_barrier ();
6360
6361         mono_image_lock (image);
6362
6363     // Here "klass2" refers to the klass potentially created by the other thread.
6364         if (pinfo) // Repeat check from above
6365                 klass2 = pinfo->pklass;
6366         else
6367                 klass2 = get_anon_gparam_class (param, FALSE);
6368
6369         if (klass2) {
6370                 klass = klass2;
6371         } else {
6372                 // Cache here
6373                 if (pinfo)
6374                         pinfo->pklass = klass;
6375                 else
6376                         set_anon_gparam_class (param, klass);
6377         }
6378         mono_image_unlock (image);
6379
6380         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6381         if (klass2)
6382                 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6383         else
6384                 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6385
6386         return klass;
6387 }
6388
6389 /**
6390  * mono_class_from_generic_parameter:
6391  * @param: Parameter to find/construct a class for.
6392  * @arg2: Is ignored.
6393  * @arg3: Is ignored.
6394  */
6395 MonoClass *
6396 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6397 {
6398         return mono_class_from_generic_parameter_internal (param);
6399 }
6400
6401
6402 MonoClass *
6403 mono_ptr_class_get (MonoType *type)
6404 {
6405         MonoClass *result;
6406         MonoClass *el_class;
6407         MonoImage *image;
6408         char *name;
6409
6410         el_class = mono_class_from_mono_type (type);
6411         image = el_class->image;
6412
6413         mono_image_lock (image);
6414         if (image->ptr_cache) {
6415                 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6416                         mono_image_unlock (image);
6417                         return result;
6418                 }
6419         }
6420         mono_image_unlock (image);
6421         
6422         result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6423
6424         classes_size += sizeof (MonoClass);
6425
6426         result->parent = NULL; /* no parent for PTR types */
6427         result->name_space = el_class->name_space;
6428         name = g_strdup_printf ("%s*", el_class->name);
6429         result->name = mono_image_strdup (image, name);
6430         g_free (name);
6431
6432         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6433
6434         result->image = el_class->image;
6435         result->inited = TRUE;
6436         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
6437         /* Can pointers get boxed? */
6438         result->instance_size = sizeof (gpointer);
6439         result->cast_class = result->element_class = el_class;
6440         result->blittable = TRUE;
6441
6442         result->byval_arg.type = MONO_TYPE_PTR;
6443         result->this_arg.type = result->byval_arg.type;
6444         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6445         result->this_arg.byref = TRUE;
6446
6447         mono_class_setup_supertypes (result);
6448
6449         mono_image_lock (image);
6450         if (image->ptr_cache) {
6451                 MonoClass *result2;
6452                 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6453                         mono_image_unlock (image);
6454                         mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6455                         return result2;
6456                 }
6457         } else {
6458                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6459         }
6460         g_hash_table_insert (image->ptr_cache, el_class, result);
6461         mono_image_unlock (image);
6462
6463         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6464
6465         return result;
6466 }
6467
6468 static MonoClass *
6469 mono_fnptr_class_get (MonoMethodSignature *sig)
6470 {
6471         MonoClass *result;
6472         static GHashTable *ptr_hash = NULL;
6473
6474         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6475
6476         mono_loader_lock ();
6477
6478         if (!ptr_hash)
6479                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6480         
6481         if ((result = (MonoClass *)g_hash_table_lookup (ptr_hash, sig))) {
6482                 mono_loader_unlock ();
6483                 return result;
6484         }
6485         result = g_new0 (MonoClass, 1);
6486
6487         result->parent = NULL; /* no parent for PTR types */
6488         result->name_space = "System";
6489         result->name = "MonoFNPtrFakeClass";
6490
6491         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6492
6493         result->image = mono_defaults.corlib; /* need to fix... */
6494         result->inited = TRUE;
6495         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
6496         /* Can pointers get boxed? */
6497         result->instance_size = sizeof (gpointer);
6498         result->cast_class = result->element_class = result;
6499         result->blittable = TRUE;
6500
6501         result->byval_arg.type = MONO_TYPE_FNPTR;
6502         result->this_arg.type = result->byval_arg.type;
6503         result->this_arg.data.method = result->byval_arg.data.method = sig;
6504         result->this_arg.byref = TRUE;
6505         result->blittable = TRUE;
6506
6507         mono_class_setup_supertypes (result);
6508
6509         g_hash_table_insert (ptr_hash, sig, result);
6510
6511         mono_loader_unlock ();
6512
6513         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6514
6515         return result;
6516 }
6517
6518 /**
6519  * mono_class_from_mono_type:
6520  * @type: describes the type to return
6521  *
6522  * This returns a MonoClass for the specified MonoType, the value is never NULL.
6523  */
6524 MonoClass *
6525 mono_class_from_mono_type (MonoType *type)
6526 {
6527         switch (type->type) {
6528         case MONO_TYPE_OBJECT:
6529                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6530         case MONO_TYPE_VOID:
6531                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6532         case MONO_TYPE_BOOLEAN:
6533                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6534         case MONO_TYPE_CHAR:
6535                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6536         case MONO_TYPE_I1:
6537                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6538         case MONO_TYPE_U1:
6539                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6540         case MONO_TYPE_I2:
6541                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6542         case MONO_TYPE_U2:
6543                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6544         case MONO_TYPE_I4:
6545                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6546         case MONO_TYPE_U4:
6547                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6548         case MONO_TYPE_I:
6549                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6550         case MONO_TYPE_U:
6551                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6552         case MONO_TYPE_I8:
6553                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6554         case MONO_TYPE_U8:
6555                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6556         case MONO_TYPE_R4:
6557                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6558         case MONO_TYPE_R8:
6559                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6560         case MONO_TYPE_STRING:
6561                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6562         case MONO_TYPE_TYPEDBYREF:
6563                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6564         case MONO_TYPE_ARRAY:
6565                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6566         case MONO_TYPE_PTR:
6567                 return mono_ptr_class_get (type->data.type);
6568         case MONO_TYPE_FNPTR:
6569                 return mono_fnptr_class_get (type->data.method);
6570         case MONO_TYPE_SZARRAY:
6571                 return mono_array_class_get (type->data.klass, 1);
6572         case MONO_TYPE_CLASS:
6573         case MONO_TYPE_VALUETYPE:
6574                 return type->data.klass;
6575         case MONO_TYPE_GENERICINST:
6576                 return mono_generic_class_get_class (type->data.generic_class);
6577         case MONO_TYPE_MVAR:
6578         case MONO_TYPE_VAR:
6579                 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6580         default:
6581                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6582                 g_assert_not_reached ();
6583         }
6584
6585         // Yes, this returns NULL, even if it is documented as not doing so, but there
6586         // is no way for the code to make it this far, due to the assert above.
6587         return NULL;
6588 }
6589
6590 /**
6591  * mono_type_retrieve_from_typespec
6592  * @image: context where the image is created
6593  * @type_spec:  typespec token
6594  * @context: the generic context used to evaluate generic instantiations in
6595  */
6596 static MonoType *
6597 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6598 {
6599         MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6600
6601         *did_inflate = FALSE;
6602
6603         if (!t)
6604                 return NULL;
6605
6606         if (context && (context->class_inst || context->method_inst)) {
6607                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6608
6609                 if (!mono_error_ok (error)) {
6610                         return NULL;
6611                 }
6612
6613                 if (inflated) {
6614                         t = inflated;
6615                         *did_inflate = TRUE;
6616                 }
6617         }
6618         return t;
6619 }
6620
6621 /**
6622  * mono_class_create_from_typespec
6623  * @image: context where the image is created
6624  * @type_spec:  typespec token
6625  * @context: the generic context used to evaluate generic instantiations in
6626  */
6627 static MonoClass *
6628 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6629 {
6630         MonoClass *ret;
6631         gboolean inflated = FALSE;
6632         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6633         return_val_if_nok (error, NULL);
6634         ret = mono_class_from_mono_type (t);
6635         if (inflated)
6636                 mono_metadata_free_type (t);
6637         return ret;
6638 }
6639
6640 /**
6641  * mono_bounded_array_class_get:
6642  * @element_class: element class 
6643  * @rank: the dimension of the array class
6644  * @bounded: whenever the array has non-zero bounds
6645  *
6646  * Returns: A class object describing the array with element type @element_type and 
6647  * dimension @rank. 
6648  */
6649 MonoClass *
6650 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6651 {
6652         MonoImage *image;
6653         MonoClass *klass;
6654         MonoClass *parent = NULL;
6655         GSList *list, *rootlist = NULL;
6656         int nsize;
6657         char *name;
6658         gboolean corlib_type = FALSE;
6659
6660         g_assert (rank <= 255);
6661
6662         if (rank > 1)
6663                 /* bounded only matters for one-dimensional arrays */
6664                 bounded = FALSE;
6665
6666         image = eclass->image;
6667
6668         if (rank == 1 && !bounded) {
6669                 /* 
6670                  * This case is very frequent not just during compilation because of calls 
6671                  * from mono_class_from_mono_type (), mono_array_new (), 
6672                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6673                  */
6674                 mono_os_mutex_lock (&image->szarray_cache_lock);
6675                 if (!image->szarray_cache)
6676                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6677                 klass = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6678                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6679                 if (klass)
6680                         return klass;
6681
6682                 mono_loader_lock ();
6683         } else {
6684                 mono_loader_lock ();
6685
6686                 if (!image->array_cache)
6687                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6688
6689                 if ((rootlist = list = (GSList *)g_hash_table_lookup (image->array_cache, eclass))) {
6690                         for (; list; list = list->next) {
6691                                 klass = (MonoClass *)list->data;
6692                                 if ((klass->rank == rank) && (klass->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6693                                         mono_loader_unlock ();
6694                                         return klass;
6695                                 }
6696                         }
6697                 }
6698         }
6699
6700         /* for the building corlib use System.Array from it */
6701         if (image->assembly && assembly_is_dynamic (image->assembly) && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
6702                 parent = mono_class_load_from_name (image, "System", "Array");
6703                 corlib_type = TRUE;
6704         } else {
6705                 parent = mono_defaults.array_class;
6706                 if (!parent->inited)
6707                         mono_class_init (parent);
6708         }
6709
6710         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClass));
6711
6712         klass->image = image;
6713         klass->name_space = eclass->name_space;
6714         nsize = strlen (eclass->name);
6715         name = (char *)g_malloc (nsize + 2 + rank + 1);
6716         memcpy (name, eclass->name, nsize);
6717         name [nsize] = '[';
6718         if (rank > 1)
6719                 memset (name + nsize + 1, ',', rank - 1);
6720         if (bounded)
6721                 name [nsize + rank] = '*';
6722         name [nsize + rank + bounded] = ']';
6723         name [nsize + rank + bounded + 1] = 0;
6724         klass->name = mono_image_strdup (image, name);
6725         g_free (name);
6726
6727         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6728
6729         classes_size += sizeof (MonoClass);
6730
6731         klass->type_token = 0;
6732         /* all arrays are marked serializable and sealed, bug #42779 */
6733         klass->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED | TYPE_ATTRIBUTE_PUBLIC;
6734         klass->parent = parent;
6735         klass->instance_size = mono_class_instance_size (klass->parent);
6736
6737         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6738                 /*Arrays of those two types are invalid.*/
6739                 mono_class_set_failure (klass, MONO_EXCEPTION_INVALID_PROGRAM, NULL);
6740         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6741                 if (!eclass->ref_info_handle || eclass->wastypebuilder) {
6742                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6743                         g_assert (eclass->ref_info_handle && !eclass->wastypebuilder);
6744                 }
6745                 /* element_size -1 is ok as this is not an instantitable type*/
6746                 klass->sizes.element_size = -1;
6747         } else
6748                 klass->sizes.element_size = mono_class_array_element_size (eclass);
6749
6750         mono_class_setup_supertypes (klass);
6751
6752         if (eclass->generic_class)
6753                 mono_class_init (eclass);
6754         if (!eclass->size_inited)
6755                 mono_class_setup_fields (eclass);
6756         if (mono_class_has_failure (eclass)) /*FIXME we fail the array type, but we have to let other fields be set.*/
6757                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, NULL);
6758
6759         klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6760
6761         klass->rank = rank;
6762         
6763         if (eclass->enumtype)
6764                 klass->cast_class = eclass->element_class;
6765         else
6766                 klass->cast_class = eclass;
6767
6768         switch (klass->cast_class->byval_arg.type) {
6769         case MONO_TYPE_I1:
6770                 klass->cast_class = mono_defaults.byte_class;
6771                 break;
6772         case MONO_TYPE_U2:
6773                 klass->cast_class = mono_defaults.int16_class;
6774                 break;
6775         case MONO_TYPE_U4:
6776 #if SIZEOF_VOID_P == 4
6777         case MONO_TYPE_I:
6778         case MONO_TYPE_U:
6779 #endif
6780                 klass->cast_class = mono_defaults.int32_class;
6781                 break;
6782         case MONO_TYPE_U8:
6783 #if SIZEOF_VOID_P == 8
6784         case MONO_TYPE_I:
6785         case MONO_TYPE_U:
6786 #endif
6787                 klass->cast_class = mono_defaults.int64_class;
6788                 break;
6789         default:
6790                 break;
6791         }
6792
6793         klass->element_class = eclass;
6794
6795         if ((rank > 1) || bounded) {
6796                 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6797                 klass->byval_arg.type = MONO_TYPE_ARRAY;
6798                 klass->byval_arg.data.array = at;
6799                 at->eklass = eclass;
6800                 at->rank = rank;
6801                 /* FIXME: complete.... */
6802         } else {
6803                 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6804                 klass->byval_arg.data.klass = eclass;
6805         }
6806         klass->this_arg = klass->byval_arg;
6807         klass->this_arg.byref = 1;
6808         if (corlib_type) {
6809                 klass->inited = 1;
6810         }
6811
6812         klass->generic_container = eclass->generic_container;
6813
6814         if (rank == 1 && !bounded) {
6815                 MonoClass *prev_class;
6816
6817                 mono_os_mutex_lock (&image->szarray_cache_lock);
6818                 prev_class = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6819                 if (prev_class)
6820                         /* Someone got in before us */
6821                         klass = prev_class;
6822                 else
6823                         g_hash_table_insert (image->szarray_cache, eclass, klass);
6824                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6825         } else {
6826                 list = g_slist_append (rootlist, klass);
6827                 g_hash_table_insert (image->array_cache, eclass, list);
6828         }
6829
6830         mono_loader_unlock ();
6831
6832         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6833
6834         return klass;
6835 }
6836
6837 /**
6838  * mono_array_class_get:
6839  * @element_class: element class 
6840  * @rank: the dimension of the array class
6841  *
6842  * Returns: A class object describing the array with element type @element_type and 
6843  * dimension @rank. 
6844  */
6845 MonoClass *
6846 mono_array_class_get (MonoClass *eclass, guint32 rank)
6847 {
6848         return mono_bounded_array_class_get (eclass, rank, FALSE);
6849 }
6850
6851 /**
6852  * mono_class_instance_size:
6853  * @klass: a class 
6854  *
6855  * Use to get the size of a class in bytes.
6856  *
6857  * Returns: The size of an object instance
6858  */
6859 gint32
6860 mono_class_instance_size (MonoClass *klass)
6861 {       
6862         if (!klass->size_inited)
6863                 mono_class_init (klass);
6864
6865         return klass->instance_size;
6866 }
6867
6868 /**
6869  * mono_class_min_align:
6870  * @klass: a class 
6871  *
6872  * Use to get the computed minimum alignment requirements for the specified class.
6873  *
6874  * Returns: minimm alignment requirements 
6875  */
6876 gint32
6877 mono_class_min_align (MonoClass *klass)
6878 {       
6879         if (!klass->size_inited)
6880                 mono_class_init (klass);
6881
6882         return klass->min_align;
6883 }
6884
6885 /**
6886  * mono_class_value_size:
6887  * @klass: a class 
6888  *
6889  * This function is used for value types, and return the
6890  * space and the alignment to store that kind of value object.
6891  *
6892  * Returns: the size of a value of kind @klass
6893  */
6894 gint32
6895 mono_class_value_size      (MonoClass *klass, guint32 *align)
6896 {
6897         gint32 size;
6898
6899         /* fixme: check disable, because we still have external revereces to
6900          * mscorlib and Dummy Objects 
6901          */
6902         /*g_assert (klass->valuetype);*/
6903
6904         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6905
6906         if (align)
6907                 *align = klass->min_align;
6908
6909         return size;
6910 }
6911
6912 /**
6913  * mono_class_data_size:
6914  * @klass: a class 
6915  * 
6916  * Returns: The size of the static class data
6917  */
6918 gint32
6919 mono_class_data_size (MonoClass *klass)
6920 {       
6921         if (!klass->inited)
6922                 mono_class_init (klass);
6923         /* This can happen with dynamically created types */
6924         if (!klass->fields_inited)
6925                 mono_class_setup_fields_locking (klass);
6926
6927         /* in arrays, sizes.class_size is unioned with element_size
6928          * and arrays have no static fields
6929          */
6930         if (klass->rank)
6931                 return 0;
6932         return klass->sizes.class_size;
6933 }
6934
6935 /*
6936  * Auxiliary routine to mono_class_get_field
6937  *
6938  * Takes a field index instead of a field token.
6939  */
6940 static MonoClassField *
6941 mono_class_get_field_idx (MonoClass *klass, int idx)
6942 {
6943         mono_class_setup_fields_locking (klass);
6944         if (mono_class_has_failure (klass))
6945                 return NULL;
6946
6947         while (klass) {
6948                 if (klass->image->uncompressed_metadata) {
6949                         /* 
6950                          * klass->field.first points to the FieldPtr table, while idx points into the
6951                          * Field table, so we have to do a search.
6952                          */
6953                         /*FIXME this is broken for types with multiple fields with the same name.*/
6954                         const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6955                         int i;
6956
6957                         for (i = 0; i < klass->field.count; ++i)
6958                                 if (mono_field_get_name (&klass->fields [i]) == name)
6959                                         return &klass->fields [i];
6960                         g_assert_not_reached ();
6961                 } else {                        
6962                         if (klass->field.count) {
6963                                 if ((idx >= klass->field.first) && (idx < klass->field.first + klass->field.count)){
6964                                         return &klass->fields [idx - klass->field.first];
6965                                 }
6966                         }
6967                 }
6968                 klass = klass->parent;
6969         }
6970         return NULL;
6971 }
6972
6973 /**
6974  * mono_class_get_field:
6975  * @class: the class to lookup the field.
6976  * @field_token: the field token
6977  *
6978  * Returns: A MonoClassField representing the type and offset of
6979  * the field, or a NULL value if the field does not belong to this
6980  * class.
6981  */
6982 MonoClassField *
6983 mono_class_get_field (MonoClass *klass, guint32 field_token)
6984 {
6985         int idx = mono_metadata_token_index (field_token);
6986
6987         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6988
6989         return mono_class_get_field_idx (klass, idx - 1);
6990 }
6991
6992 /**
6993  * mono_class_get_field_from_name:
6994  * @klass: the class to lookup the field.
6995  * @name: the field name
6996  *
6997  * Search the class @klass and it's parents for a field with the name @name.
6998  * 
6999  * Returns: The MonoClassField pointer of the named field or NULL
7000  */
7001 MonoClassField *
7002 mono_class_get_field_from_name (MonoClass *klass, const char *name)
7003 {
7004         return mono_class_get_field_from_name_full (klass, name, NULL);
7005 }
7006
7007 /**
7008  * mono_class_get_field_from_name_full:
7009  * @klass: the class to lookup the field.
7010  * @name: the field name
7011  * @type: the type of the fields. This optional.
7012  *
7013  * Search the class @klass and it's parents for a field with the name @name and type @type.
7014  *
7015  * If @klass is an inflated generic type, the type comparison is done with the equivalent field
7016  * of its generic type definition.
7017  *
7018  * Returns: The MonoClassField pointer of the named field or NULL
7019  */
7020 MonoClassField *
7021 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
7022 {
7023         int i;
7024
7025         mono_class_setup_fields_locking (klass);
7026         if (mono_class_has_failure (klass))
7027                 return NULL;
7028
7029         while (klass) {
7030                 for (i = 0; i < klass->field.count; ++i) {
7031                         MonoClassField *field = &klass->fields [i];
7032
7033                         if (strcmp (name, mono_field_get_name (field)) != 0)
7034                                 continue;
7035
7036                         if (type) {
7037                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
7038                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
7039                                         continue;
7040                         }
7041                         return field;
7042                 }
7043                 klass = klass->parent;
7044         }
7045         return NULL;
7046 }
7047
7048 /**
7049  * mono_class_get_field_token:
7050  * @field: the field we need the token of
7051  *
7052  * Get the token of a field. Note that the tokesn is only valid for the image
7053  * the field was loaded from. Don't use this function for fields in dynamic types.
7054  * 
7055  * Returns: The token representing the field in the image it was loaded from.
7056  */
7057 guint32
7058 mono_class_get_field_token (MonoClassField *field)
7059 {
7060         MonoClass *klass = field->parent;
7061         int i;
7062
7063         mono_class_setup_fields_locking (klass);
7064
7065         while (klass) {
7066                 if (!klass->fields)
7067                         return 0;
7068                 for (i = 0; i < klass->field.count; ++i) {
7069                         if (&klass->fields [i] == field) {
7070                                 int idx = klass->field.first + i + 1;
7071
7072                                 if (klass->image->uncompressed_metadata)
7073                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
7074                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
7075                         }
7076                 }
7077                 klass = klass->parent;
7078         }
7079
7080         g_assert_not_reached ();
7081         return 0;
7082 }
7083
7084 static int
7085 mono_field_get_index (MonoClassField *field)
7086 {
7087         int index = field - field->parent->fields;
7088
7089         g_assert (index >= 0 && index < field->parent->field.count);
7090
7091         return index;
7092 }
7093
7094 /*
7095  * mono_class_get_field_default_value:
7096  *
7097  * Return the default value of the field as a pointer into the metadata blob.
7098  */
7099 const char*
7100 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
7101 {
7102         guint32 cindex;
7103         guint32 constant_cols [MONO_CONSTANT_SIZE];
7104         int field_index;
7105         MonoClass *klass = field->parent;
7106
7107         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
7108
7109         if (!klass->ext || !klass->ext->field_def_values) {
7110                 MonoFieldDefaultValue *def_values;
7111
7112                 mono_class_alloc_ext (klass);
7113
7114                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
7115
7116                 mono_image_lock (klass->image);
7117                 mono_memory_barrier ();
7118                 if (!klass->ext->field_def_values)
7119                         klass->ext->field_def_values = def_values;
7120                 mono_image_unlock (klass->image);
7121         }
7122
7123         field_index = mono_field_get_index (field);
7124                 
7125         if (!klass->ext->field_def_values [field_index].data) {
7126                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
7127                 if (!cindex)
7128                         return NULL;
7129
7130                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
7131
7132                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7133                 klass->ext->field_def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7134                 klass->ext->field_def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
7135         }
7136
7137         *def_type = klass->ext->field_def_values [field_index].def_type;
7138         return klass->ext->field_def_values [field_index].data;
7139 }
7140
7141 static int
7142 mono_property_get_index (MonoProperty *prop)
7143 {
7144         int index = prop - prop->parent->ext->properties;
7145
7146         g_assert (index >= 0 && index < prop->parent->ext->property.count);
7147
7148         return index;
7149 }
7150
7151 /*
7152  * mono_class_get_property_default_value:
7153  *
7154  * Return the default value of the field as a pointer into the metadata blob.
7155  */
7156 const char*
7157 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7158 {
7159         guint32 cindex;
7160         guint32 constant_cols [MONO_CONSTANT_SIZE];
7161         MonoClass *klass = property->parent;
7162
7163         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7164         /*
7165          * We don't cache here because it is not used by C# so it's quite rare, but
7166          * we still do the lookup in klass->ext because that is where the data
7167          * is stored for dynamic assemblies.
7168          */
7169
7170         if (image_is_dynamic (klass->image)) {
7171                 int prop_index = mono_property_get_index (property);
7172                 if (klass->ext->prop_def_values && klass->ext->prop_def_values [prop_index].data) {
7173                         *def_type = klass->ext->prop_def_values [prop_index].def_type;
7174                         return klass->ext->prop_def_values [prop_index].data;
7175                 }
7176                 return NULL;
7177         }
7178         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7179         if (!cindex)
7180                 return NULL;
7181
7182         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7183         *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7184         return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7185 }
7186
7187 guint32
7188 mono_class_get_event_token (MonoEvent *event)
7189 {
7190         MonoClass *klass = event->parent;
7191         int i;
7192
7193         while (klass) {
7194                 if (klass->ext) {
7195                         for (i = 0; i < klass->ext->event.count; ++i) {
7196                                 if (&klass->ext->events [i] == event)
7197                                         return mono_metadata_make_token (MONO_TABLE_EVENT, klass->ext->event.first + i + 1);
7198                         }
7199                 }
7200                 klass = klass->parent;
7201         }
7202
7203         g_assert_not_reached ();
7204         return 0;
7205 }
7206
7207 /**
7208  * mono_class_get_property_from_name:
7209  * @klass: a class
7210  * @name: name of the property to lookup in the specified class
7211  *
7212  * Use this method to lookup a property in a class
7213  * Returns: the MonoProperty with the given name, or NULL if the property
7214  * does not exist on the @klass.
7215  */
7216 MonoProperty*
7217 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7218 {
7219         while (klass) {
7220                 MonoProperty* p;
7221                 gpointer iter = NULL;
7222                 while ((p = mono_class_get_properties (klass, &iter))) {
7223                         if (! strcmp (name, p->name))
7224                                 return p;
7225                 }
7226                 klass = klass->parent;
7227         }
7228         return NULL;
7229 }
7230
7231 /**
7232  * mono_class_get_property_token:
7233  * @prop: MonoProperty to query
7234  *
7235  * Returns: The ECMA token for the specified property.
7236  */
7237 guint32
7238 mono_class_get_property_token (MonoProperty *prop)
7239 {
7240         MonoClass *klass = prop->parent;
7241         while (klass) {
7242                 MonoProperty* p;
7243                 int i = 0;
7244                 gpointer iter = NULL;
7245                 while ((p = mono_class_get_properties (klass, &iter))) {
7246                         if (&klass->ext->properties [i] == prop)
7247                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->ext->property.first + i + 1);
7248                         
7249                         i ++;
7250                 }
7251                 klass = klass->parent;
7252         }
7253
7254         g_assert_not_reached ();
7255         return 0;
7256 }
7257
7258 char *
7259 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7260 {
7261         const char *name, *nspace;
7262         if (image_is_dynamic (image))
7263                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7264         
7265         switch (type_token & 0xff000000){
7266         case MONO_TOKEN_TYPE_DEF: {
7267                 guint32 cols [MONO_TYPEDEF_SIZE];
7268                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7269                 guint tidx = mono_metadata_token_index (type_token);
7270
7271                 if (tidx > tt->rows)
7272                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7273
7274                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7275                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7276                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7277                 if (strlen (nspace) == 0)
7278                         return g_strdup_printf ("%s", name);
7279                 else
7280                         return g_strdup_printf ("%s.%s", nspace, name);
7281         }
7282
7283         case MONO_TOKEN_TYPE_REF: {
7284                 MonoError error;
7285                 guint32 cols [MONO_TYPEREF_SIZE];
7286                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7287                 guint tidx = mono_metadata_token_index (type_token);
7288
7289                 if (tidx > t->rows)
7290                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7291
7292                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7293                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7294                         mono_error_cleanup (&error);
7295                         return msg;
7296                 }
7297
7298                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7299                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7300                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7301                 if (strlen (nspace) == 0)
7302                         return g_strdup_printf ("%s", name);
7303                 else
7304                         return g_strdup_printf ("%s.%s", nspace, name);
7305         }
7306                 
7307         case MONO_TOKEN_TYPE_SPEC:
7308                 return g_strdup_printf ("Typespec 0x%08x", type_token);
7309         default:
7310                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7311         }
7312 }
7313
7314 static char *
7315 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7316 {
7317         if (image_is_dynamic (image))
7318                 return g_strdup_printf ("DynamicAssembly %s", image->name);
7319         
7320         switch (type_token & 0xff000000){
7321         case MONO_TOKEN_TYPE_DEF:
7322                 if (image->assembly)
7323                         return mono_stringify_assembly_name (&image->assembly->aname);
7324                 else if (image->assembly_name)
7325                         return g_strdup (image->assembly_name);
7326                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7327         case MONO_TOKEN_TYPE_REF: {
7328                 MonoError error;
7329                 MonoAssemblyName aname;
7330                 guint32 cols [MONO_TYPEREF_SIZE];
7331                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7332                 guint32 idx = mono_metadata_token_index (type_token);
7333
7334                 if (idx > t->rows)
7335                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7336         
7337                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7338                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7339                         mono_error_cleanup (&error);
7340                         return msg;
7341                 }
7342                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7343
7344                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7345                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7346                 case MONO_RESOLUTION_SCOPE_MODULE:
7347                         /* FIXME: */
7348                         return g_strdup ("");
7349                 case MONO_RESOLUTION_SCOPE_MODULEREF:
7350                         /* FIXME: */
7351                         return g_strdup ("");
7352                 case MONO_RESOLUTION_SCOPE_TYPEREF:
7353                         /* FIXME: */
7354                         return g_strdup ("");
7355                 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7356                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7357                         return mono_stringify_assembly_name (&aname);
7358                 default:
7359                         g_assert_not_reached ();
7360                 }
7361                 break;
7362         }
7363         case MONO_TOKEN_TYPE_SPEC:
7364                 /* FIXME: */
7365                 return g_strdup ("");
7366         default:
7367                 g_assert_not_reached ();
7368         }
7369
7370         return NULL;
7371 }
7372
7373 /**
7374  * mono_class_get_full:
7375  * @image: the image where the class resides
7376  * @type_token: the token for the class
7377  * @context: the generic context used to evaluate generic instantiations in
7378  * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7379  *
7380  * Returns: The MonoClass that represents @type_token in @image
7381  */
7382 MonoClass *
7383 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7384 {
7385         MonoError error;
7386         MonoClass *klass;
7387         klass = mono_class_get_checked (image, type_token, &error);
7388
7389         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7390                 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7391
7392         g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7393         return klass;
7394 }
7395
7396
7397 MonoClass *
7398 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7399 {
7400         MonoClass *klass;
7401
7402         mono_error_init (error);
7403         klass = mono_class_get_checked (image, type_token, error);
7404
7405         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7406                 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7407
7408         return klass;
7409 }
7410 /**
7411  * mono_class_get_checked:
7412  * @image: the image where the class resides
7413  * @type_token: the token for the class
7414  * @error: error object to return any error
7415  *
7416  * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7417  */
7418 MonoClass *
7419 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7420 {
7421         MonoClass *klass = NULL;
7422
7423         mono_error_init (error);
7424
7425         if (image_is_dynamic (image)) {
7426                 int table = mono_metadata_token_table (type_token);
7427
7428                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7429                         mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7430                         return NULL;
7431                 }
7432                 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7433                 goto done;
7434         }
7435
7436         switch (type_token & 0xff000000){
7437         case MONO_TOKEN_TYPE_DEF:
7438                 klass = mono_class_create_from_typedef (image, type_token, error);
7439                 break;          
7440         case MONO_TOKEN_TYPE_REF:
7441                 klass = mono_class_from_typeref_checked (image, type_token, error);
7442                 break;
7443         case MONO_TOKEN_TYPE_SPEC:
7444                 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7445                 break;
7446         default:
7447                 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7448         }
7449
7450 done:
7451         /* Generic case, should be avoided for when a better error is possible. */
7452         if (!klass && mono_error_ok (error)) {
7453                 char *name = mono_class_name_from_token (image, type_token);
7454                 char *assembly = mono_assembly_name_from_token (image, type_token);
7455                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7456         }
7457
7458         return klass;
7459 }
7460
7461
7462 /**
7463  * mono_type_get_checked:
7464  * @image: the image where the type resides
7465  * @type_token: the token for the type
7466  * @context: the generic context used to evaluate generic instantiations in
7467  * @error: Error handling context
7468  *
7469  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7470  * 
7471  * Returns: The MonoType that represents @type_token in @image
7472  */
7473 MonoType *
7474 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7475 {
7476         MonoType *type = NULL;
7477         gboolean inflated = FALSE;
7478
7479         mono_error_init (error);
7480
7481         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7482         if (image_is_dynamic (image)) {
7483                 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7484                 return_val_if_nok (error, NULL);
7485                 return mono_class_get_type (klass);
7486         }
7487
7488         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7489                 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7490
7491                 if (!klass) {
7492                         return NULL;
7493                 }
7494
7495                 g_assert (klass);
7496                 return mono_class_get_type (klass);
7497         }
7498
7499         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7500
7501         if (!type) {
7502                 return NULL;
7503         }
7504
7505         if (inflated) {
7506                 MonoType *tmp = type;
7507                 type = mono_class_get_type (mono_class_from_mono_type (type));
7508                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7509                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7510                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7511                  *
7512                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7513                  * */
7514                 if (type->type != tmp->type)
7515                         type = tmp;
7516                 else
7517                         mono_metadata_free_type (tmp);
7518         }
7519         return type;
7520 }
7521
7522 /**
7523  * mono_class_get:
7524  * @image: image where the class token will be looked up.
7525  * @type_token: a type token from the image
7526  *
7527  * Returns the MonoClass with the given @type_token on the @image
7528  */
7529 MonoClass *
7530 mono_class_get (MonoImage *image, guint32 type_token)
7531 {
7532         return mono_class_get_full (image, type_token, NULL);
7533 }
7534
7535 /**
7536  * mono_image_init_name_cache:
7537  *
7538  *  Initializes the class name cache stored in image->name_cache.
7539  *
7540  * LOCKING: Acquires the corresponding image lock.
7541  */
7542 void
7543 mono_image_init_name_cache (MonoImage *image)
7544 {
7545         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7546         guint32 cols [MONO_TYPEDEF_SIZE];
7547         const char *name;
7548         const char *nspace;
7549         guint32 i, visib, nspace_index;
7550         GHashTable *name_cache2, *nspace_table, *the_name_cache;
7551
7552         if (image->name_cache)
7553                 return;
7554
7555         the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7556
7557         if (image_is_dynamic (image)) {
7558                 mono_image_lock (image);
7559                 if (image->name_cache) {
7560                         /* Somebody initialized it before us */
7561                         g_hash_table_destroy (the_name_cache);
7562                 } else {
7563                         mono_atomic_store_release (&image->name_cache, the_name_cache);
7564                 }
7565                 mono_image_unlock (image);
7566                 return;
7567         }
7568
7569         /* Temporary hash table to avoid lookups in the nspace_table */
7570         name_cache2 = g_hash_table_new (NULL, NULL);
7571
7572         for (i = 1; i <= t->rows; ++i) {
7573                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7574                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7575                 /*
7576                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7577                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7578                  */
7579                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7580                         continue;
7581                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7582                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7583
7584                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7585                 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7586                 if (!nspace_table) {
7587                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7588                         g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7589                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7590                                                                  nspace_table);
7591                 }
7592                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7593         }
7594
7595         /* Load type names from EXPORTEDTYPES table */
7596         {
7597                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7598                 guint32 cols [MONO_EXP_TYPE_SIZE];
7599                 int i;
7600
7601                 for (i = 0; i < t->rows; ++i) {
7602                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7603
7604                         guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7605                         if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7606                                 /* Nested type */
7607                                 continue;
7608
7609                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7610                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7611
7612                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7613                         nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7614                         if (!nspace_table) {
7615                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7616                                 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7617                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7618                                                                          nspace_table);
7619                         }
7620                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7621                 }
7622         }
7623
7624         g_hash_table_destroy (name_cache2);
7625
7626         mono_image_lock (image);
7627         if (image->name_cache) {
7628                 /* Somebody initialized it before us */
7629                 g_hash_table_destroy (the_name_cache);
7630         } else {
7631                 mono_atomic_store_release (&image->name_cache, the_name_cache);
7632         }
7633         mono_image_unlock (image);
7634 }
7635
7636 /*FIXME Only dynamic assemblies should allow this operation.*/
7637 void
7638 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7639                                                           const char *name, guint32 index)
7640 {
7641         GHashTable *nspace_table;
7642         GHashTable *name_cache;
7643         guint32 old_index;
7644
7645         mono_image_init_name_cache (image);
7646         mono_image_lock (image);
7647
7648         name_cache = image->name_cache;
7649         if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7650                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7651                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7652         }
7653
7654         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7655                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7656
7657         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7658
7659         mono_image_unlock (image);
7660 }
7661
7662 typedef struct {
7663         gconstpointer key;
7664         gpointer value;
7665 } FindUserData;
7666
7667 static void
7668 find_nocase (gpointer key, gpointer value, gpointer user_data)
7669 {
7670         char *name = (char*)key;
7671         FindUserData *data = (FindUserData*)user_data;
7672
7673         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7674                 data->value = value;
7675 }
7676
7677 /**
7678  * mono_class_from_name_case:
7679  * @image: The MonoImage where the type is looked up in
7680  * @name_space: the type namespace
7681  * @name: the type short name.
7682  * @deprecated: use the mono_class_from_name_case_checked variant instead.
7683  *
7684  * Obtains a MonoClass with a given namespace and a given name which
7685  * is located in the given MonoImage.   The namespace and name
7686  * lookups are case insensitive.
7687  */
7688 MonoClass *
7689 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7690 {
7691         MonoError error;
7692         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7693         mono_error_cleanup (&error);
7694
7695         return res;
7696 }
7697
7698 /**
7699  * mono_class_from_name_case:
7700  * @image: The MonoImage where the type is looked up in
7701  * @name_space: the type namespace
7702  * @name: the type short name.
7703  * @error: if 
7704  *
7705  * Obtains a MonoClass with a given namespace and a given name which
7706  * is located in the given MonoImage.   The namespace and name
7707  * lookups are case insensitive.
7708  *
7709  * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7710  * was not found.   The @error object will contain information about the problem
7711  * in that case.
7712  */
7713 MonoClass *
7714 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7715 {
7716         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7717         guint32 cols [MONO_TYPEDEF_SIZE];
7718         const char *n;
7719         const char *nspace;
7720         guint32 i, visib;
7721
7722         mono_error_init (error);
7723
7724         if (image_is_dynamic (image)) {
7725                 guint32 token = 0;
7726                 FindUserData user_data;
7727
7728                 mono_image_init_name_cache (image);
7729                 mono_image_lock (image);
7730
7731                 user_data.key = name_space;
7732                 user_data.value = NULL;
7733                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7734
7735                 if (user_data.value) {
7736                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7737
7738                         user_data.key = name;
7739                         user_data.value = NULL;
7740
7741                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7742                         
7743                         if (user_data.value)
7744                                 token = GPOINTER_TO_UINT (user_data.value);
7745                 }
7746
7747                 mono_image_unlock (image);
7748                 
7749                 if (token)
7750                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7751                 else
7752                         return NULL;
7753
7754         }
7755
7756         /* add a cache if needed */
7757         for (i = 1; i <= t->rows; ++i) {
7758                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7759                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7760                 /*
7761                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7762                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7763                  */
7764                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7765                         continue;
7766                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7767                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7768                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7769                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7770         }
7771         return NULL;
7772 }
7773
7774 static MonoClass*
7775 return_nested_in (MonoClass *klass, char *nested)
7776 {
7777         MonoClass *found;
7778         char *s = strchr (nested, '/');
7779         gpointer iter = NULL;
7780
7781         if (s) {
7782                 *s = 0;
7783                 s++;
7784         }
7785
7786         while ((found = mono_class_get_nested_types (klass, &iter))) {
7787                 if (strcmp (found->name, nested) == 0) {
7788                         if (s)
7789                                 return return_nested_in (found, s);
7790                         return found;
7791                 }
7792         }
7793         return NULL;
7794 }
7795
7796 static MonoClass*
7797 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7798 {
7799         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7800         MonoImage *file_image;
7801         MonoClass *klass;
7802         int i;
7803
7804         mono_error_init (error);
7805
7806         /* 
7807          * The EXPORTEDTYPES table only contains public types, so have to search the
7808          * modules as well.
7809          * Note: image->modules contains the contents of the MODULEREF table, while
7810          * the real module list is in the FILE table.
7811          */
7812         for (i = 0; i < file_table->rows; i++) {
7813                 guint32 cols [MONO_FILE_SIZE];
7814                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7815                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7816                         continue;
7817
7818                 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7819                 if (file_image) {
7820                         klass = mono_class_from_name_checked (file_image, name_space, name, error);
7821                         if (klass || !is_ok (error))
7822                                 return klass;
7823                 }
7824         }
7825
7826         return NULL;
7827 }
7828
7829 static MonoClass *
7830 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7831 {
7832         GHashTable *nspace_table;
7833         MonoImage *loaded_image;
7834         guint32 token = 0;
7835         int i;
7836         MonoClass *klass;
7837         char *nested;
7838         char buf [1024];
7839
7840         mono_error_init (error);
7841
7842         // Checking visited images avoids stack overflows when cyclic references exist.
7843         if (g_hash_table_lookup (visited_images, image))
7844                 return NULL;
7845
7846         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7847
7848         if ((nested = strchr (name, '/'))) {
7849                 int pos = nested - name;
7850                 int len = strlen (name);
7851                 if (len > 1023)
7852                         return NULL;
7853                 memcpy (buf, name, len + 1);
7854                 buf [pos] = 0;
7855                 nested = buf + pos + 1;
7856                 name = buf;
7857         }
7858
7859         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7860         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7861                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7862                 if (res) {
7863                         if (!klass) {
7864                                 klass = search_modules (image, name_space, name, error);
7865                                 if (!is_ok (error))
7866                                         return NULL;
7867                         }
7868                         if (nested)
7869                                 return klass ? return_nested_in (klass, nested) : NULL;
7870                         else
7871                                 return klass;
7872                 }
7873         }
7874
7875         mono_image_init_name_cache (image);
7876         mono_image_lock (image);
7877
7878         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7879
7880         if (nspace_table)
7881                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7882
7883         mono_image_unlock (image);
7884
7885         if (!token && image_is_dynamic (image) && image->modules) {
7886                 /* Search modules as well */
7887                 for (i = 0; i < image->module_count; ++i) {
7888                         MonoImage *module = image->modules [i];
7889
7890                         klass = mono_class_from_name_checked (module, name_space, name, error);
7891                         if (klass || !is_ok (error))
7892                                 return klass;
7893                 }
7894         }
7895
7896         if (!token) {
7897                 klass = search_modules (image, name_space, name, error);
7898                 if (klass || !is_ok (error))
7899                         return klass;
7900                 return NULL;
7901         }
7902
7903         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7904                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7905                 guint32 cols [MONO_EXP_TYPE_SIZE];
7906                 guint32 idx, impl;
7907
7908                 idx = mono_metadata_token_index (token);
7909
7910                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7911
7912                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7913                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7914                         loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7915                         if (!loaded_image)
7916                                 return NULL;
7917                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7918                         if (nested)
7919                                 return klass ? return_nested_in (klass, nested) : NULL;
7920                         return klass;
7921                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7922                         guint32 assembly_idx;
7923
7924                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7925
7926                         mono_assembly_load_reference (image, assembly_idx - 1);
7927                         g_assert (image->references [assembly_idx - 1]);
7928                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7929                                 return NULL;                    
7930                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7931                         if (nested)
7932                                 return klass ? return_nested_in (klass, nested) : NULL;
7933                         return klass;
7934                 } else {
7935                         g_assert_not_reached ();
7936                 }
7937         }
7938
7939         token = MONO_TOKEN_TYPE_DEF | token;
7940
7941         klass = mono_class_get_checked (image, token, error);
7942         if (nested)
7943                 return return_nested_in (klass, nested);
7944         return klass;
7945 }
7946
7947 /**
7948  * mono_class_from_name_checked:
7949  * @image: The MonoImage where the type is looked up in
7950  * @name_space: the type namespace
7951  * @name: the type short name.
7952  *
7953  * Obtains a MonoClass with a given namespace and a given name which
7954  * is located in the given MonoImage.
7955  *
7956  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7957  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7958  */
7959 MonoClass *
7960 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7961 {
7962         MonoClass *klass;
7963         GHashTable *visited_images;
7964
7965         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7966
7967         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7968
7969         g_hash_table_destroy (visited_images);
7970
7971         return klass;
7972 }
7973
7974 /**
7975  * mono_class_from_name:
7976  * @image: The MonoImage where the type is looked up in
7977  * @name_space: the type namespace
7978  * @name: the type short name.
7979  *
7980  * Obtains a MonoClass with a given namespace and a given name which
7981  * is located in the given MonoImage.
7982  *
7983  * To reference nested classes, use the "/" character as a separator.
7984  * For example use "Foo/Bar" to reference the class Bar that is nested
7985  * inside Foo, like this: "class Foo { class Bar {} }".
7986  */
7987 MonoClass *
7988 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7989 {
7990         MonoError error;
7991         MonoClass *klass;
7992
7993         klass = mono_class_from_name_checked (image, name_space, name, &error);
7994         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7995
7996         return klass;
7997 }
7998
7999 /**
8000  * mono_class_load_from_name:
8001  * @image: The MonoImage where the type is looked up in
8002  * @name_space: the type namespace
8003  * @name: the type short name.
8004  *
8005  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8006  * This function should be used by the runtime for critical types to which there's no way to recover but crash
8007  * If they are missing. Thing of System.Object or System.String.
8008  */
8009 MonoClass *
8010 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8011 {
8012         MonoError error;
8013         MonoClass *klass;
8014
8015         klass = mono_class_from_name_checked (image, name_space, name, &error);
8016         if (!klass)
8017                 g_error ("Runtime critical type %s.%s not found", name_space, name);
8018         if (!mono_error_ok (&error))
8019                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8020         return klass;
8021 }
8022
8023 /**
8024  * mono_class_try_load_from_name:
8025  * @image: The MonoImage where the type is looked up in
8026  * @name_space: the type namespace
8027  * @name: the type short name.
8028  *
8029  * This function tries to load a type, returning the class was found or NULL otherwise.
8030  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8031  *
8032  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8033  * a type that we would otherwise assume to be available but was not due some error.
8034  *
8035  */
8036 MonoClass*
8037 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8038 {
8039         MonoError error;
8040         MonoClass *klass;
8041
8042         klass = mono_class_from_name_checked (image, name_space, name, &error);
8043         if (!mono_error_ok (&error))
8044                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8045         return klass;
8046 }
8047
8048
8049 /**
8050  * mono_class_is_subclass_of:
8051  * @klass: class to probe if it is a subclass of another one
8052  * @klassc: the class we suspect is the base class
8053  * @check_interfaces: whether we should perform interface checks
8054  *
8055  * This method determines whether @klass is a subclass of @klassc.
8056  *
8057  * If the @check_interfaces flag is set, then if @klassc is an interface
8058  * this method return TRUE if the @klass implements the interface or
8059  * if @klass is an interface, if one of its base classes is @klass.
8060  *
8061  * If @check_interfaces is false then, then if @klass is not an interface
8062  * then it returns TRUE if the @klass is a subclass of @klassc.
8063  *
8064  * if @klass is an interface and @klassc is System.Object, then this function
8065  * return true.
8066  *
8067  */
8068 gboolean
8069 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
8070                            gboolean check_interfaces)
8071 {
8072         /* FIXME test for interfaces with variant generic arguments */
8073         mono_class_init (klass);
8074         mono_class_init (klassc);
8075         
8076         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8077                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8078                         return TRUE;
8079         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8080                 int i;
8081
8082                 for (i = 0; i < klass->interface_count; i ++) {
8083                         MonoClass *ic =  klass->interfaces [i];
8084                         if (ic == klassc)
8085                                 return TRUE;
8086                 }
8087         } else {
8088                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8089                         return TRUE;
8090         }
8091
8092         /* 
8093          * MS.NET thinks interfaces are a subclass of Object, so we think it as
8094          * well.
8095          */
8096         if (klassc == mono_defaults.object_class)
8097                 return TRUE;
8098
8099         return FALSE;
8100 }
8101
8102 static gboolean
8103 mono_type_is_generic_argument (MonoType *type)
8104 {
8105         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8106 }
8107
8108 gboolean
8109 mono_class_has_variant_generic_params (MonoClass *klass)
8110 {
8111         int i;
8112         MonoGenericContainer *container;
8113
8114         if (!klass->generic_class)
8115                 return FALSE;
8116
8117         container = klass->generic_class->container_class->generic_container;
8118
8119         for (i = 0; i < container->type_argc; ++i)
8120                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8121                         return TRUE;
8122
8123         return FALSE;
8124 }
8125
8126 static gboolean
8127 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8128 {
8129         if (target == candidate)
8130                 return TRUE;
8131
8132         if (check_for_reference_conv &&
8133                 mono_type_is_generic_argument (&target->byval_arg) &&
8134                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8135                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8136                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8137
8138                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8139                         return FALSE;
8140         }
8141         if (!mono_class_is_assignable_from (target, candidate))
8142                 return FALSE;
8143         return TRUE;
8144 }
8145
8146 /**
8147  * @container the generic container from the GTD
8148  * @klass: the class to be assigned to
8149  * @oklass: the source class
8150  * 
8151  * Both @klass and @oklass must be instances of the same generic interface.
8152  *
8153  * Returns: TRUE if @klass can be assigned to a @klass variable
8154  */
8155 gboolean
8156 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8157 {
8158         int j;
8159         MonoType **klass_argv, **oklass_argv;
8160         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8161         MonoGenericContainer *container = klass_gtd->generic_container;
8162
8163         if (klass == oklass)
8164                 return TRUE;
8165
8166         /*Viable candidates are instances of the same generic interface*/
8167         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8168                 return FALSE;
8169
8170         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8171         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8172
8173         for (j = 0; j < container->type_argc; ++j) {
8174                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8175                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8176
8177                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8178                         return FALSE;
8179
8180                 /*
8181                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8182                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8183                  */
8184                 if (param1_class != param2_class) {
8185                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8186                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8187                                         return FALSE;
8188                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8189                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8190                                         return FALSE;
8191                         } else
8192                                 return FALSE;
8193                 }
8194         }
8195         return TRUE;
8196 }
8197
8198 static gboolean
8199 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8200 {
8201         MonoGenericParam *gparam, *ogparam;
8202         MonoGenericParamInfo *tinfo, *cinfo;
8203         MonoClass **candidate_class;
8204         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8205         int tmask, cmask;
8206
8207         if (target == candidate)
8208                 return TRUE;
8209         if (target->byval_arg.type != candidate->byval_arg.type)
8210                 return FALSE;
8211
8212         gparam = target->byval_arg.data.generic_param;
8213         ogparam = candidate->byval_arg.data.generic_param;
8214         tinfo = mono_generic_param_info (gparam);
8215         cinfo = mono_generic_param_info (ogparam);
8216
8217         class_constraint_satisfied = FALSE;
8218         valuetype_constraint_satisfied = FALSE;
8219
8220         /*candidate must have a super set of target's special constraints*/
8221         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8222         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8223
8224         if (cinfo->constraints) {
8225                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8226                         MonoClass *cc = *candidate_class;
8227
8228                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8229                                 class_constraint_satisfied = TRUE;
8230                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8231                                 valuetype_constraint_satisfied = TRUE;
8232                 }
8233         }
8234         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8235         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8236
8237         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8238                 return FALSE;
8239         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8240                 return FALSE;
8241         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8242                 valuetype_constraint_satisfied)) {
8243                 return FALSE;
8244         }
8245
8246
8247         /*candidate type constraints must be a superset of target's*/
8248         if (tinfo->constraints) {
8249                 MonoClass **target_class;
8250                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8251                         MonoClass *tc = *target_class;
8252
8253                         /*
8254                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8255                          * check it's constraints since it satisfy the constraint by itself.
8256                          */
8257                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8258                                 continue;
8259
8260                         if (!cinfo->constraints)
8261                                 return FALSE;
8262
8263                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8264                                 MonoClass *cc = *candidate_class;
8265
8266                                 if (mono_class_is_assignable_from (tc, cc))
8267                                         break;
8268
8269                                 /*
8270                                  * This happens when we have the following:
8271                                  *
8272                                  * Bar<K> where K : IFace
8273                                  * Foo<T, U> where T : U where U : IFace
8274                                  *      ...
8275                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8276                                  *
8277                                  */
8278                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8279                                         if (mono_gparam_is_assignable_from (target, cc))
8280                                                 break;
8281                                 }
8282                         }
8283                         if (!*candidate_class)
8284                                 return FALSE;
8285                 }
8286         }
8287
8288         /*candidate itself must have a constraint that satisfy target*/
8289         if (cinfo->constraints) {
8290                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8291                         MonoClass *cc = *candidate_class;
8292                         if (mono_class_is_assignable_from (target, cc))
8293                                 return TRUE;
8294                 }
8295         }
8296         return FALSE;
8297 }
8298
8299 /**
8300  * mono_class_is_assignable_from:
8301  * @klass: the class to be assigned to
8302  * @oklass: the source class
8303  *
8304  * Returns: TRUE if an instance of object oklass can be assigned to an
8305  * instance of object @klass
8306  */
8307 gboolean
8308 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8309 {
8310         MonoError error;
8311         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8312         if (!klass->inited)
8313                 mono_class_init (klass);
8314
8315         if (!oklass->inited)
8316                 mono_class_init (oklass);
8317
8318         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8319                 return FALSE;
8320
8321         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8322                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8323                         return FALSE;
8324                 return mono_gparam_is_assignable_from (klass, oklass);
8325         }
8326
8327         if (MONO_CLASS_IS_INTERFACE (klass)) {
8328                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8329                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8330                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8331                         int i;
8332
8333                         if (constraints) {
8334                                 for (i = 0; constraints [i]; ++i) {
8335                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8336                                                 return TRUE;
8337                                 }
8338                         }
8339
8340                         return FALSE;
8341                 }
8342
8343                 /* interface_offsets might not be set for dynamic classes */
8344                 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8345                         /* 
8346                          * oklass might be a generic type parameter but they have 
8347                          * interface_offsets set.
8348                          */
8349                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8350                         if (!is_ok (&error)) {
8351                                 mono_error_cleanup (&error);
8352                                 return FALSE;
8353                         }
8354                         return result;
8355                 }
8356                 if (!oklass->interface_bitmap)
8357                         /* Happens with generic instances of not-yet created dynamic types */
8358                         return FALSE;
8359                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8360                         return TRUE;
8361
8362                 if (mono_class_has_variant_generic_params (klass)) {
8363                         int i;
8364                         mono_class_setup_interfaces (oklass, &error);
8365                         if (!mono_error_ok (&error)) {
8366                                 mono_error_cleanup (&error);
8367                                 return FALSE;
8368                         }
8369
8370                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8371                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8372                                 MonoClass *iface = oklass->interfaces_packed [i];
8373
8374                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8375                                         return TRUE;
8376                         }
8377                 }
8378                 return FALSE;
8379         } else if (klass->delegate) {
8380                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8381                         return TRUE;
8382         }else if (klass->rank) {
8383                 MonoClass *eclass, *eoclass;
8384
8385                 if (oklass->rank != klass->rank)
8386                         return FALSE;
8387
8388                 /* vectors vs. one dimensional arrays */
8389                 if (oklass->byval_arg.type != klass->byval_arg.type)
8390                         return FALSE;
8391
8392                 eclass = klass->cast_class;
8393                 eoclass = oklass->cast_class;
8394
8395                 /* 
8396                  * a is b does not imply a[] is b[] when a is a valuetype, and
8397                  * b is a reference type.
8398                  */
8399
8400                 if (eoclass->valuetype) {
8401                         if ((eclass == mono_defaults.enum_class) || 
8402                                 (eclass == mono_defaults.enum_class->parent) ||
8403                                 (eclass == mono_defaults.object_class))
8404                                 return FALSE;
8405                 }
8406
8407                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8408         } else if (mono_class_is_nullable (klass)) {
8409                 if (mono_class_is_nullable (oklass))
8410                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8411                 else
8412                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8413         } else if (klass == mono_defaults.object_class)
8414                 return TRUE;
8415
8416         return mono_class_has_parent (oklass, klass);
8417 }       
8418
8419 /*Check if @oklass is variant compatible with @klass.*/
8420 static gboolean
8421 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8422 {
8423         int j;
8424         MonoType **klass_argv, **oklass_argv;
8425         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8426         MonoGenericContainer *container = klass_gtd->generic_container;
8427
8428         /*Viable candidates are instances of the same generic interface*/
8429         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8430                 return FALSE;
8431
8432         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8433         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8434
8435         for (j = 0; j < container->type_argc; ++j) {
8436                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8437                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8438
8439                 if (param1_class->valuetype != param2_class->valuetype)
8440                         return FALSE;
8441
8442                 /*
8443                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8444                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8445                  */
8446                 if (param1_class != param2_class) {
8447                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8448                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8449                                         return FALSE;
8450                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8451                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8452                                         return FALSE;
8453                         } else
8454                                 return FALSE;
8455                 }
8456         }
8457         return TRUE;
8458 }
8459 /*Check if @candidate implements the interface @target*/
8460 static gboolean
8461 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8462 {
8463         MonoError error;
8464         int i;
8465         gboolean is_variant = mono_class_has_variant_generic_params (target);
8466
8467         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8468                 if (mono_class_is_variant_compatible_slow (target, candidate))
8469                         return TRUE;
8470         }
8471
8472         do {
8473                 if (candidate == target)
8474                         return TRUE;
8475
8476                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8477                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8478                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8479                         int j;
8480                         if (tb && tb->interfaces) {
8481                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8482                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8483                                         MonoClass *iface_class;
8484
8485                                         /* we can't realize the type here since it can do pretty much anything. */
8486                                         if (!iface->type)
8487                                                 continue;
8488                                         iface_class = mono_class_from_mono_type (iface->type);
8489                                         if (iface_class == target)
8490                                                 return TRUE;
8491                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8492                                                 return TRUE;
8493                                         if (mono_class_implement_interface_slow (target, iface_class))
8494                                                 return TRUE;
8495                                 }
8496                         }
8497                 } else {
8498                         /*setup_interfaces don't mono_class_init anything*/
8499                         /*FIXME this doesn't handle primitive type arrays.
8500                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8501                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8502                         */
8503                         mono_class_setup_interfaces (candidate, &error);
8504                         if (!mono_error_ok (&error)) {
8505                                 mono_error_cleanup (&error);
8506                                 return FALSE;
8507                         }
8508
8509                         for (i = 0; i < candidate->interface_count; ++i) {
8510                                 if (candidate->interfaces [i] == target)
8511                                         return TRUE;
8512                                 
8513                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8514                                         return TRUE;
8515
8516                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8517                                         return TRUE;
8518                         }
8519                 }
8520                 candidate = candidate->parent;
8521         } while (candidate);
8522
8523         return FALSE;
8524 }
8525
8526 /*
8527  * Check if @oklass can be assigned to @klass.
8528  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8529  */
8530 gboolean
8531 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8532 {
8533         if (candidate == target)
8534                 return TRUE;
8535         if (target == mono_defaults.object_class)
8536                 return TRUE;
8537
8538         if (mono_class_has_parent (candidate, target))
8539                 return TRUE;
8540
8541         /*If target is not an interface there is no need to check them.*/
8542         if (MONO_CLASS_IS_INTERFACE (target))
8543                 return mono_class_implement_interface_slow (target, candidate);
8544
8545         if (target->delegate && mono_class_has_variant_generic_params (target))
8546                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8547
8548         if (target->rank) {
8549                 MonoClass *eclass, *eoclass;
8550
8551                 if (target->rank != candidate->rank)
8552                         return FALSE;
8553
8554                 /* vectors vs. one dimensional arrays */
8555                 if (target->byval_arg.type != candidate->byval_arg.type)
8556                         return FALSE;
8557
8558                 eclass = target->cast_class;
8559                 eoclass = candidate->cast_class;
8560
8561                 /*
8562                  * a is b does not imply a[] is b[] when a is a valuetype, and
8563                  * b is a reference type.
8564                  */
8565
8566                 if (eoclass->valuetype) {
8567                         if ((eclass == mono_defaults.enum_class) ||
8568                                 (eclass == mono_defaults.enum_class->parent) ||
8569                                 (eclass == mono_defaults.object_class))
8570                                 return FALSE;
8571                 }
8572
8573                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8574         }
8575         /*FIXME properly handle nullables */
8576         /*FIXME properly handle (M)VAR */
8577         return FALSE;
8578 }
8579
8580 /**
8581  * mono_class_get_cctor:
8582  * @klass: A MonoClass pointer
8583  *
8584  * Returns: The static constructor of @klass if it exists, NULL otherwise.
8585  */
8586 MonoMethod*
8587 mono_class_get_cctor (MonoClass *klass)
8588 {
8589         MonoCachedClassInfo cached_info;
8590
8591         if (image_is_dynamic (klass->image)) {
8592                 /* 
8593                  * has_cctor is not set for these classes because mono_class_init () is
8594                  * not run for them.
8595                  */
8596                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8597         }
8598
8599         if (!klass->has_cctor)
8600                 return NULL;
8601
8602         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8603                 MonoError error;
8604                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8605                 if (!mono_error_ok (&error))
8606                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8607                 return result;
8608         }
8609
8610         if (klass->generic_class && !klass->methods)
8611                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8612
8613         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8614 }
8615
8616 /**
8617  * mono_class_get_finalizer:
8618  * @klass: The MonoClass pointer
8619  *
8620  * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8621  */
8622 MonoMethod*
8623 mono_class_get_finalizer (MonoClass *klass)
8624 {
8625         MonoCachedClassInfo cached_info;
8626
8627         if (!klass->inited)
8628                 mono_class_init (klass);
8629         if (!mono_class_has_finalizer (klass))
8630                 return NULL;
8631
8632         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8633                 MonoError error;
8634                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8635                 if (!mono_error_ok (&error))
8636                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8637                 return result;
8638         }else {
8639                 mono_class_setup_vtable (klass);
8640                 return klass->vtable [finalize_slot];
8641         }
8642 }
8643
8644 /**
8645  * mono_class_needs_cctor_run:
8646  * @klass: the MonoClass pointer
8647  * @caller: a MonoMethod describing the caller
8648  *
8649  * Determines whenever the class has a static constructor and whenever it
8650  * needs to be called when executing CALLER.
8651  */
8652 gboolean
8653 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8654 {
8655         MonoMethod *method;
8656
8657         method = mono_class_get_cctor (klass);
8658         if (method)
8659                 return (method == caller) ? FALSE : TRUE;
8660         else
8661                 return FALSE;
8662 }
8663
8664 /**
8665  * mono_class_array_element_size:
8666  * @klass: 
8667  *
8668  * Returns: The number of bytes an element of type @klass
8669  * uses when stored into an array.
8670  */
8671 gint32
8672 mono_class_array_element_size (MonoClass *klass)
8673 {
8674         MonoType *type = &klass->byval_arg;
8675         
8676 handle_enum:
8677         switch (type->type) {
8678         case MONO_TYPE_I1:
8679         case MONO_TYPE_U1:
8680         case MONO_TYPE_BOOLEAN:
8681                 return 1;
8682         case MONO_TYPE_I2:
8683         case MONO_TYPE_U2:
8684         case MONO_TYPE_CHAR:
8685                 return 2;
8686         case MONO_TYPE_I4:
8687         case MONO_TYPE_U4:
8688         case MONO_TYPE_R4:
8689                 return 4;
8690         case MONO_TYPE_I:
8691         case MONO_TYPE_U:
8692         case MONO_TYPE_PTR:
8693         case MONO_TYPE_CLASS:
8694         case MONO_TYPE_STRING:
8695         case MONO_TYPE_OBJECT:
8696         case MONO_TYPE_SZARRAY:
8697         case MONO_TYPE_ARRAY: 
8698                 return sizeof (gpointer);
8699         case MONO_TYPE_I8:
8700         case MONO_TYPE_U8:
8701         case MONO_TYPE_R8:
8702                 return 8;
8703         case MONO_TYPE_VALUETYPE:
8704                 if (type->data.klass->enumtype) {
8705                         type = mono_class_enum_basetype (type->data.klass);
8706                         klass = klass->element_class;
8707                         goto handle_enum;
8708                 }
8709                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8710         case MONO_TYPE_GENERICINST:
8711                 type = &type->data.generic_class->container_class->byval_arg;
8712                 goto handle_enum;
8713         case MONO_TYPE_VAR:
8714         case MONO_TYPE_MVAR: {
8715                 int align;
8716
8717                 return mono_type_size (type, &align);
8718         }
8719         case MONO_TYPE_VOID:
8720                 return 0;
8721                 
8722         default:
8723                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8724         }
8725         return -1;
8726 }
8727
8728 /**
8729  * mono_array_element_size:
8730  * @ac: pointer to a #MonoArrayClass
8731  *
8732  * Returns: The size of single array element.
8733  */
8734 gint32
8735 mono_array_element_size (MonoClass *ac)
8736 {
8737         g_assert (ac->rank);
8738         return ac->sizes.element_size;
8739 }
8740
8741 gpointer
8742 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8743               MonoGenericContext *context)
8744 {
8745         MonoError error;
8746         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8747         g_assert (mono_error_ok (&error));
8748         return res;
8749 }
8750
8751 gpointer
8752 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8753               MonoGenericContext *context, MonoError *error)
8754 {
8755         mono_error_init (error);
8756
8757         if (image_is_dynamic (image)) {
8758                 MonoClass *tmp_handle_class;
8759                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8760
8761                 mono_error_assert_ok (error);
8762                 g_assert (tmp_handle_class);
8763                 if (handle_class)
8764                         *handle_class = tmp_handle_class;
8765
8766                 if (tmp_handle_class == mono_defaults.typehandle_class)
8767                         return &((MonoClass*)obj)->byval_arg;
8768                 else
8769                         return obj;
8770         }
8771
8772         switch (token & 0xff000000) {
8773         case MONO_TOKEN_TYPE_DEF:
8774         case MONO_TOKEN_TYPE_REF:
8775         case MONO_TOKEN_TYPE_SPEC: {
8776                 MonoType *type;
8777                 if (handle_class)
8778                         *handle_class = mono_defaults.typehandle_class;
8779                 type = mono_type_get_checked (image, token, context, error);
8780                 if (!type)
8781                         return NULL;
8782
8783                 mono_class_init (mono_class_from_mono_type (type));
8784                 /* We return a MonoType* as handle */
8785                 return type;
8786         }
8787         case MONO_TOKEN_FIELD_DEF: {
8788                 MonoClass *klass;
8789                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8790                 if (!type) {
8791                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8792                         return NULL;
8793                 }
8794                 if (handle_class)
8795                         *handle_class = mono_defaults.fieldhandle_class;
8796                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8797                 if (!klass)
8798                         return NULL;
8799
8800                 mono_class_init (klass);
8801                 return mono_class_get_field (klass, token);
8802         }
8803         case MONO_TOKEN_METHOD_DEF:
8804         case MONO_TOKEN_METHOD_SPEC: {
8805                 MonoMethod *meth;
8806                 meth = mono_get_method_checked (image, token, NULL, context, error);
8807                 if (handle_class)
8808                         *handle_class = mono_defaults.methodhandle_class;
8809                 if (!meth)
8810                         return NULL;
8811
8812                 return meth;
8813         }
8814         case MONO_TOKEN_MEMBER_REF: {
8815                 guint32 cols [MONO_MEMBERREF_SIZE];
8816                 const char *sig;
8817                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8818                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8819                 mono_metadata_decode_blob_size (sig, &sig);
8820                 if (*sig == 0x6) { /* it's a field */
8821                         MonoClass *klass;
8822                         MonoClassField *field;
8823                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8824                         if (handle_class)
8825                                 *handle_class = mono_defaults.fieldhandle_class;
8826                         return field;
8827                 } else {
8828                         MonoMethod *meth;
8829                         meth = mono_get_method_checked (image, token, NULL, context, error);
8830                         if (handle_class)
8831                                 *handle_class = mono_defaults.methodhandle_class;
8832                         return meth;
8833                 }
8834         }
8835         default:
8836                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8837         }
8838         return NULL;
8839 }
8840
8841 gpointer
8842 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8843 {
8844         MonoClass *handle_class;
8845         mono_error_init (error);
8846         return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8847 }
8848
8849 gpointer
8850 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8851 {
8852         return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8853 }
8854
8855 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8856
8857 void
8858 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8859 {
8860         get_cached_class_info = func;
8861 }
8862
8863 static gboolean
8864 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8865 {
8866         if (!get_cached_class_info)
8867                 return FALSE;
8868         else
8869                 return get_cached_class_info (klass, res);
8870 }
8871
8872 void
8873 mono_install_get_class_from_name (MonoGetClassFromName func)
8874 {
8875         get_class_from_name = func;
8876 }
8877
8878 /**
8879  * mono_class_get_image:
8880  *
8881  * Use this method to get the `MonoImage*` where this class came from.
8882  *
8883  * Returns: The image where this class is defined.
8884  */
8885 MonoImage*
8886 mono_class_get_image (MonoClass *klass)
8887 {
8888         return klass->image;
8889 }
8890
8891 /**
8892  * mono_class_get_element_class:
8893  * @klass: the MonoClass to act on
8894  *
8895  * Use this function to get the element class of an array.
8896  *
8897  * Returns: The element class of an array.
8898  */
8899 MonoClass*
8900 mono_class_get_element_class (MonoClass *klass)
8901 {
8902         return klass->element_class;
8903 }
8904
8905 /**
8906  * mono_class_is_valuetype:
8907  * @klass: the MonoClass to act on
8908  *
8909  * Use this method to determine if the provided `MonoClass*` represents a value type,
8910  * or a reference type.
8911  *
8912  * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8913  */
8914 gboolean
8915 mono_class_is_valuetype (MonoClass *klass)
8916 {
8917         return klass->valuetype;
8918 }
8919
8920 /**
8921  * mono_class_is_enum:
8922  * @klass: the MonoClass to act on
8923  *
8924  * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8925  *
8926  * Returns: TRUE if the MonoClass represents an enumeration.
8927  */
8928 gboolean
8929 mono_class_is_enum (MonoClass *klass)
8930 {
8931         return klass->enumtype;
8932 }
8933
8934 /**
8935  * mono_class_enum_basetype:
8936  * @klass: the MonoClass to act on
8937  *
8938  * Use this function to get the underlying type for an enumeration value.
8939  * 
8940  * Returns: The underlying type representation for an enumeration.
8941  */
8942 MonoType*
8943 mono_class_enum_basetype (MonoClass *klass)
8944 {
8945         if (klass->element_class == klass)
8946                 /* SRE or broken types */
8947                 return NULL;
8948         else
8949                 return &klass->element_class->byval_arg;
8950 }
8951
8952 /**
8953  * mono_class_get_parent
8954  * @klass: the MonoClass to act on
8955  *
8956  * Returns: The parent class for this class.
8957  */
8958 MonoClass*
8959 mono_class_get_parent (MonoClass *klass)
8960 {
8961         return klass->parent;
8962 }
8963
8964 /**
8965  * mono_class_get_nesting_type:
8966  * @klass: the MonoClass to act on
8967  *
8968  * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8969  *
8970  * If the return is NULL, this indicates that this class is not nested.
8971  *
8972  * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8973  */
8974 MonoClass*
8975 mono_class_get_nesting_type (MonoClass *klass)
8976 {
8977         return klass->nested_in;
8978 }
8979
8980 /**
8981  * mono_class_get_rank:
8982  * @klass: the MonoClass to act on
8983  *
8984  * Returns: The rank for the array (the number of dimensions).
8985  */
8986 int
8987 mono_class_get_rank (MonoClass *klass)
8988 {
8989         return klass->rank;
8990 }
8991
8992 /**
8993  * mono_class_get_flags:
8994  * @klass: the MonoClass to act on
8995  *
8996  * The type flags from the TypeDef table from the metadata.
8997  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
8998  * different values.
8999  *
9000  * Returns: The flags from the TypeDef table.
9001  */
9002 guint32
9003 mono_class_get_flags (MonoClass *klass)
9004 {
9005         return klass->flags;
9006 }
9007
9008 /**
9009  * mono_class_get_name
9010  * @klass: the MonoClass to act on
9011  *
9012  * Returns: The name of the class.
9013  */
9014 const char*
9015 mono_class_get_name (MonoClass *klass)
9016 {
9017         return klass->name;
9018 }
9019
9020 /**
9021  * mono_class_get_namespace:
9022  * @klass: the MonoClass to act on
9023  *
9024  * Returns: The namespace of the class.
9025  */
9026 const char*
9027 mono_class_get_namespace (MonoClass *klass)
9028 {
9029         return klass->name_space;
9030 }
9031
9032 /**
9033  * mono_class_get_type:
9034  * @klass: the MonoClass to act on
9035  *
9036  * This method returns the internal Type representation for the class.
9037  *
9038  * Returns: The MonoType from the class.
9039  */
9040 MonoType*
9041 mono_class_get_type (MonoClass *klass)
9042 {
9043         return &klass->byval_arg;
9044 }
9045
9046 /**
9047  * mono_class_get_type_token:
9048  * @klass: the MonoClass to act on
9049  *
9050  * This method returns type token for the class.
9051  *
9052  * Returns: The type token for the class.
9053  */
9054 guint32
9055 mono_class_get_type_token (MonoClass *klass)
9056 {
9057   return klass->type_token;
9058 }
9059
9060 /**
9061  * mono_class_get_byref_type:
9062  * @klass: the MonoClass to act on
9063  *
9064  * 
9065  */
9066 MonoType*
9067 mono_class_get_byref_type (MonoClass *klass)
9068 {
9069         return &klass->this_arg;
9070 }
9071
9072 /**
9073  * mono_class_num_fields:
9074  * @klass: the MonoClass to act on
9075  *
9076  * Returns: The number of static and instance fields in the class.
9077  */
9078 int
9079 mono_class_num_fields (MonoClass *klass)
9080 {
9081         return klass->field.count;
9082 }
9083
9084 /**
9085  * mono_class_num_methods:
9086  * @klass: the MonoClass to act on
9087  *
9088  * Returns: The number of methods in the class.
9089  */
9090 int
9091 mono_class_num_methods (MonoClass *klass)
9092 {
9093         return klass->method.count;
9094 }
9095
9096 /**
9097  * mono_class_num_properties
9098  * @klass: the MonoClass to act on
9099  *
9100  * Returns: The number of properties in the class.
9101  */
9102 int
9103 mono_class_num_properties (MonoClass *klass)
9104 {
9105         mono_class_setup_properties (klass);
9106
9107         return klass->ext->property.count;
9108 }
9109
9110 /**
9111  * mono_class_num_events:
9112  * @klass: the MonoClass to act on
9113  *
9114  * Returns: The number of events in the class.
9115  */
9116 int
9117 mono_class_num_events (MonoClass *klass)
9118 {
9119         mono_class_setup_events (klass);
9120
9121         return klass->ext->event.count;
9122 }
9123
9124 /**
9125  * mono_class_get_fields:
9126  * @klass: the MonoClass to act on
9127  *
9128  * This routine is an iterator routine for retrieving the fields in a class.
9129  *
9130  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9131  * iterate over all of the elements.  When no more values are
9132  * available, the return value is NULL.
9133  *
9134  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9135  */
9136 MonoClassField*
9137 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9138 {
9139         MonoClassField* field;
9140         if (!iter)
9141                 return NULL;
9142         if (!*iter) {
9143                 mono_class_setup_fields_locking (klass);
9144                 if (mono_class_has_failure (klass))
9145                         return NULL;
9146                 /* start from the first */
9147                 if (klass->field.count) {
9148                         *iter = &klass->fields [0];
9149                         return &klass->fields [0];
9150                 } else {
9151                         /* no fields */
9152                         return NULL;
9153                 }
9154         }
9155         field = (MonoClassField *)*iter;
9156         field++;
9157         if (field < &klass->fields [klass->field.count]) {
9158                 *iter = field;
9159                 return field;
9160         }
9161         return NULL;
9162 }
9163
9164 /**
9165  * mono_class_get_methods
9166  * @klass: the MonoClass to act on
9167  *
9168  * This routine is an iterator routine for retrieving the fields in a class.
9169  *
9170  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9171  * iterate over all of the elements.  When no more values are
9172  * available, the return value is NULL.
9173  *
9174  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9175  */
9176 MonoMethod*
9177 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9178 {
9179         MonoMethod** method;
9180         if (!iter)
9181                 return NULL;
9182         if (!*iter) {
9183                 mono_class_setup_methods (klass);
9184
9185                 /*
9186                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9187                  * FIXME we should better report this error to the caller
9188                  */
9189                 if (!klass->methods)
9190                         return NULL;
9191                 /* start from the first */
9192                 if (klass->method.count) {
9193                         *iter = &klass->methods [0];
9194                         return klass->methods [0];
9195                 } else {
9196                         /* no method */
9197                         return NULL;
9198                 }
9199         }
9200         method = (MonoMethod **)*iter;
9201         method++;
9202         if (method < &klass->methods [klass->method.count]) {
9203                 *iter = method;
9204                 return *method;
9205         }
9206         return NULL;
9207 }
9208
9209 /*
9210  * mono_class_get_virtual_methods:
9211  *
9212  *   Iterate over the virtual methods of KLASS.
9213  *
9214  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9215  */
9216 static MonoMethod*
9217 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9218 {
9219         MonoMethod** method;
9220         if (!iter)
9221                 return NULL;
9222         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9223                 if (!*iter) {
9224                         mono_class_setup_methods (klass);
9225                         /*
9226                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9227                          * FIXME we should better report this error to the caller
9228                          */
9229                         if (!klass->methods)
9230                                 return NULL;
9231                         /* start from the first */
9232                         method = &klass->methods [0];
9233                 } else {
9234                         method = (MonoMethod **)*iter;
9235                         method++;
9236                 }
9237                 while (method < &klass->methods [klass->method.count]) {
9238                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9239                                 break;
9240                         method ++;
9241                 }
9242                 if (method < &klass->methods [klass->method.count]) {
9243                         *iter = method;
9244                         return *method;
9245                 } else {
9246                         return NULL;
9247                 }
9248         } else {
9249                 /* Search directly in metadata to avoid calling setup_methods () */
9250                 MonoMethod *res = NULL;
9251                 int i, start_index;
9252
9253                 if (!*iter) {
9254                         start_index = 0;
9255                 } else {
9256                         start_index = GPOINTER_TO_UINT (*iter);
9257                 }
9258
9259                 for (i = start_index; i < klass->method.count; ++i) {
9260                         guint32 flags;
9261
9262                         /* klass->method.first points into the methodptr table */
9263                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9264
9265                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9266                                 break;
9267                 }
9268
9269                 if (i < klass->method.count) {
9270                         MonoError error;
9271                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9272                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9273
9274                         /* Add 1 here so the if (*iter) check fails */
9275                         *iter = GUINT_TO_POINTER (i + 1);
9276                         return res;
9277                 } else {
9278                         return NULL;
9279                 }
9280         }
9281 }
9282
9283 /**
9284  * mono_class_get_properties:
9285  * @klass: the MonoClass to act on
9286  *
9287  * This routine is an iterator routine for retrieving the properties in a class.
9288  *
9289  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9290  * iterate over all of the elements.  When no more values are
9291  * available, the return value is NULL.
9292  *
9293  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9294  */
9295 MonoProperty*
9296 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9297 {
9298         MonoProperty* property;
9299         if (!iter)
9300                 return NULL;
9301         if (!*iter) {
9302                 mono_class_setup_properties (klass);
9303                 /* start from the first */
9304                 if (klass->ext->property.count) {
9305                         *iter = &klass->ext->properties [0];
9306                         return (MonoProperty *)*iter;
9307                 } else {
9308                         /* no fields */
9309                         return NULL;
9310                 }
9311         }
9312         property = (MonoProperty *)*iter;
9313         property++;
9314         if (property < &klass->ext->properties [klass->ext->property.count]) {
9315                 *iter = property;
9316                 return (MonoProperty *)*iter;
9317         }
9318         return NULL;
9319 }
9320
9321 /**
9322  * mono_class_get_events:
9323  * @klass: the MonoClass to act on
9324  *
9325  * This routine is an iterator routine for retrieving the properties in a class.
9326  *
9327  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9328  * iterate over all of the elements.  When no more values are
9329  * available, the return value is NULL.
9330  *
9331  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9332  */
9333 MonoEvent*
9334 mono_class_get_events (MonoClass* klass, gpointer *iter)
9335 {
9336         MonoEvent* event;
9337         if (!iter)
9338                 return NULL;
9339         if (!*iter) {
9340                 mono_class_setup_events (klass);
9341                 /* start from the first */
9342                 if (klass->ext->event.count) {
9343                         *iter = &klass->ext->events [0];
9344                         return (MonoEvent *)*iter;
9345                 } else {
9346                         /* no fields */
9347                         return NULL;
9348                 }
9349         }
9350         event = (MonoEvent *)*iter;
9351         event++;
9352         if (event < &klass->ext->events [klass->ext->event.count]) {
9353                 *iter = event;
9354                 return (MonoEvent *)*iter;
9355         }
9356         return NULL;
9357 }
9358
9359 /**
9360  * mono_class_get_interfaces
9361  * @klass: the MonoClass to act on
9362  *
9363  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9364  *
9365  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9366  * iterate over all of the elements.  When no more values are
9367  * available, the return value is NULL.
9368  *
9369  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9370  */
9371 MonoClass*
9372 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9373 {
9374         MonoError error;
9375         MonoClass** iface;
9376         if (!iter)
9377                 return NULL;
9378         if (!*iter) {
9379                 if (!klass->inited)
9380                         mono_class_init (klass);
9381                 if (!klass->interfaces_inited) {
9382                         mono_class_setup_interfaces (klass, &error);
9383                         if (!mono_error_ok (&error)) {
9384                                 mono_error_cleanup (&error);
9385                                 return NULL;
9386                         }
9387                 }
9388                 /* start from the first */
9389                 if (klass->interface_count) {
9390                         *iter = &klass->interfaces [0];
9391                         return klass->interfaces [0];
9392                 } else {
9393                         /* no interface */
9394                         return NULL;
9395                 }
9396         }
9397         iface = (MonoClass **)*iter;
9398         iface++;
9399         if (iface < &klass->interfaces [klass->interface_count]) {
9400                 *iter = iface;
9401                 return *iface;
9402         }
9403         return NULL;
9404 }
9405
9406 static void
9407 setup_nested_types (MonoClass *klass)
9408 {
9409         MonoError error;
9410         GList *classes, *nested_classes, *l;
9411         int i;
9412
9413         if (klass->nested_classes_inited)
9414                 return;
9415
9416         if (!klass->type_token)
9417                 klass->nested_classes_inited = TRUE;
9418
9419         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9420         classes = NULL;
9421         while (i) {
9422                 MonoClass* nclass;
9423                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9424                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9425                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9426                 if (!mono_error_ok (&error)) {
9427                         /*FIXME don't swallow the error message*/
9428                         mono_error_cleanup (&error);
9429
9430                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9431                         continue;
9432                 }
9433
9434                 classes = g_list_prepend (classes, nclass);
9435
9436                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9437         }
9438
9439         mono_class_alloc_ext (klass);
9440
9441         nested_classes = NULL;
9442         for (l = classes; l; l = l->next)
9443                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9444         g_list_free (classes);
9445
9446         mono_image_lock (klass->image);
9447
9448         mono_memory_barrier ();
9449         if (!klass->nested_classes_inited) {
9450                 klass->ext->nested_classes = nested_classes;
9451                 mono_memory_barrier ();
9452                 klass->nested_classes_inited = TRUE;
9453         }
9454
9455         mono_image_unlock (klass->image);
9456 }
9457
9458 /**
9459  * mono_class_get_nested_types
9460  * @klass: the MonoClass to act on
9461  *
9462  * This routine is an iterator routine for retrieving the nested types of a class.
9463  * This works only if @klass is non-generic, or a generic type definition.
9464  *
9465  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9466  * iterate over all of the elements.  When no more values are
9467  * available, the return value is NULL.
9468  *
9469  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9470  */
9471 MonoClass*
9472 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9473 {
9474         GList *item;
9475
9476         if (!iter)
9477                 return NULL;
9478         if (!klass->nested_classes_inited)
9479                 setup_nested_types (klass);
9480
9481         if (!*iter) {
9482                 /* start from the first */
9483                 if (klass->ext && klass->ext->nested_classes) {
9484                         *iter = klass->ext->nested_classes;
9485                         return (MonoClass *)klass->ext->nested_classes->data;
9486                 } else {
9487                         /* no nested types */
9488                         return NULL;
9489                 }
9490         }
9491         item = (GList *)*iter;
9492         item = item->next;
9493         if (item) {
9494                 *iter = item;
9495                 return (MonoClass *)item->data;
9496         }
9497         return NULL;
9498 }
9499
9500
9501 /**
9502  * mono_class_is_delegate
9503  * @klass: the MonoClass to act on
9504  *
9505  * Returns: TRUE if the MonoClass represents a System.Delegate.
9506  */
9507 mono_bool
9508 mono_class_is_delegate (MonoClass *klass)
9509 {
9510         return klass->delegate;
9511 }
9512
9513 /**
9514  * mono_class_implements_interface
9515  * @klass: The MonoClass to act on
9516  * @interface: The interface to check if @klass implements.
9517  *
9518  * Returns: TRUE if @klass implements @interface.
9519  */
9520 mono_bool
9521 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9522 {
9523         return mono_class_is_assignable_from (iface, klass);
9524 }
9525
9526 /**
9527  * mono_field_get_name:
9528  * @field: the MonoClassField to act on
9529  *
9530  * Returns: The name of the field.
9531  */
9532 const char*
9533 mono_field_get_name (MonoClassField *field)
9534 {
9535         return field->name;
9536 }
9537
9538 /**
9539  * mono_field_get_type:
9540  * @field: the MonoClassField to act on
9541  *
9542  * Returns: MonoType of the field.
9543  */
9544 MonoType*
9545 mono_field_get_type (MonoClassField *field)
9546 {
9547         MonoError error;
9548         MonoType *type = mono_field_get_type_checked (field, &error);
9549         if (!mono_error_ok (&error)) {
9550                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9551                 mono_error_cleanup (&error);
9552         }
9553         return type;
9554 }
9555
9556
9557 /**
9558  * mono_field_get_type_checked:
9559  * @field: the MonoClassField to act on
9560  * @error: used to return any erro found while retrieving @field type
9561  *
9562  * Returns: MonoType of the field.
9563  */
9564 MonoType*
9565 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9566 {
9567         mono_error_init (error);
9568         if (!field->type)
9569                 mono_field_resolve_type (field, error);
9570         return field->type;
9571 }
9572
9573 /**
9574  * mono_field_get_parent:
9575  * @field: the MonoClassField to act on
9576  *
9577  * Returns: MonoClass where the field was defined.
9578  */
9579 MonoClass*
9580 mono_field_get_parent (MonoClassField *field)
9581 {
9582         return field->parent;
9583 }
9584
9585 /**
9586  * mono_field_get_flags;
9587  * @field: the MonoClassField to act on
9588  *
9589  * The metadata flags for a field are encoded using the
9590  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9591  *
9592  * Returns: The flags for the field.
9593  */
9594 guint32
9595 mono_field_get_flags (MonoClassField *field)
9596 {
9597         if (!field->type)
9598                 return mono_field_resolve_flags (field);
9599         return field->type->attrs;
9600 }
9601
9602 /**
9603  * mono_field_get_offset:
9604  * @field: the MonoClassField to act on
9605  *
9606  * Returns: The field offset.
9607  */
9608 guint32
9609 mono_field_get_offset (MonoClassField *field)
9610 {
9611         return field->offset;
9612 }
9613
9614 static const char *
9615 mono_field_get_rva (MonoClassField *field)
9616 {
9617         guint32 rva;
9618         int field_index;
9619         MonoClass *klass = field->parent;
9620         MonoFieldDefaultValue *field_def_values;
9621
9622         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9623
9624         if (!klass->ext || !klass->ext->field_def_values) {
9625                 mono_class_alloc_ext (klass);
9626
9627                 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9628
9629                 mono_image_lock (klass->image);
9630                 if (!klass->ext->field_def_values)
9631                         klass->ext->field_def_values = field_def_values;
9632                 mono_image_unlock (klass->image);
9633         }
9634
9635         field_index = mono_field_get_index (field);
9636                 
9637         if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9638                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9639                 if (!rva)
9640                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9641                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9642         }
9643
9644         return klass->ext->field_def_values [field_index].data;
9645 }
9646
9647 /**
9648  * mono_field_get_data:
9649  * @field: the MonoClassField to act on
9650  *
9651  * Returns: A pointer to the metadata constant value or to the field
9652  * data if it has an RVA flag.
9653  */
9654 const char *
9655 mono_field_get_data (MonoClassField *field)
9656 {
9657         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9658                 MonoTypeEnum def_type;
9659
9660                 return mono_class_get_field_default_value (field, &def_type);
9661         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9662                 return mono_field_get_rva (field);
9663         } else {
9664                 return NULL;
9665         }
9666 }
9667
9668 /**
9669  * mono_property_get_name: 
9670  * @prop: the MonoProperty to act on
9671  *
9672  * Returns: The name of the property
9673  */
9674 const char*
9675 mono_property_get_name (MonoProperty *prop)
9676 {
9677         return prop->name;
9678 }
9679
9680 /**
9681  * mono_property_get_set_method
9682  * @prop: the MonoProperty to act on.
9683  *
9684  * Returns: The setter method of the property (A MonoMethod)
9685  */
9686 MonoMethod*
9687 mono_property_get_set_method (MonoProperty *prop)
9688 {
9689         return prop->set;
9690 }
9691
9692 /**
9693  * mono_property_get_get_method
9694  * @prop: the MonoProperty to act on.
9695  *
9696  * Returns: The setter method of the property (A MonoMethod)
9697  */
9698 MonoMethod*
9699 mono_property_get_get_method (MonoProperty *prop)
9700 {
9701         return prop->get;
9702 }
9703
9704 /**
9705  * mono_property_get_parent:
9706  * @prop: the MonoProperty to act on.
9707  *
9708  * Returns: The MonoClass where the property was defined.
9709  */
9710 MonoClass*
9711 mono_property_get_parent (MonoProperty *prop)
9712 {
9713         return prop->parent;
9714 }
9715
9716 /**
9717  * mono_property_get_flags:
9718  * @prop: the MonoProperty to act on.
9719  *
9720  * The metadata flags for a property are encoded using the
9721  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9722  *
9723  * Returns: The flags for the property.
9724  */
9725 guint32
9726 mono_property_get_flags (MonoProperty *prop)
9727 {
9728         return prop->attrs;
9729 }
9730
9731 /**
9732  * mono_event_get_name:
9733  * @event: the MonoEvent to act on
9734  *
9735  * Returns: The name of the event.
9736  */
9737 const char*
9738 mono_event_get_name (MonoEvent *event)
9739 {
9740         return event->name;
9741 }
9742
9743 /**
9744  * mono_event_get_add_method:
9745  * @event: The MonoEvent to act on.
9746  *
9747  * Returns: The @add' method for the event (a MonoMethod).
9748  */
9749 MonoMethod*
9750 mono_event_get_add_method (MonoEvent *event)
9751 {
9752         return event->add;
9753 }
9754
9755 /**
9756  * mono_event_get_remove_method:
9757  * @event: The MonoEvent to act on.
9758  *
9759  * Returns: The @remove method for the event (a MonoMethod).
9760  */
9761 MonoMethod*
9762 mono_event_get_remove_method (MonoEvent *event)
9763 {
9764         return event->remove;
9765 }
9766
9767 /**
9768  * mono_event_get_raise_method:
9769  * @event: The MonoEvent to act on.
9770  *
9771  * Returns: The @raise method for the event (a MonoMethod).
9772  */
9773 MonoMethod*
9774 mono_event_get_raise_method (MonoEvent *event)
9775 {
9776         return event->raise;
9777 }
9778
9779 /**
9780  * mono_event_get_parent:
9781  * @event: the MonoEvent to act on.
9782  *
9783  * Returns: The MonoClass where the event is defined.
9784  */
9785 MonoClass*
9786 mono_event_get_parent (MonoEvent *event)
9787 {
9788         return event->parent;
9789 }
9790
9791 /**
9792  * mono_event_get_flags
9793  * @event: the MonoEvent to act on.
9794  *
9795  * The metadata flags for an event are encoded using the
9796  * EVENT_* constants.  See the tabledefs.h file for details.
9797  *
9798  * Returns: The flags for the event.
9799  */
9800 guint32
9801 mono_event_get_flags (MonoEvent *event)
9802 {
9803         return event->attrs;
9804 }
9805
9806 /**
9807  * mono_class_get_method_from_name:
9808  * @klass: where to look for the method
9809  * @name: name of the method
9810  * @param_count: number of parameters. -1 for any number.
9811  *
9812  * Obtains a MonoMethod with a given name and number of parameters.
9813  * It only works if there are no multiple signatures for any given method name.
9814  */
9815 MonoMethod *
9816 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9817 {
9818         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9819 }
9820
9821 static MonoMethod*
9822 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9823 {
9824         MonoMethod *res = NULL;
9825         int i;
9826
9827         /* Search directly in the metadata to avoid calling setup_methods () */
9828         for (i = 0; i < klass->method.count; ++i) {
9829                 MonoError error;
9830                 guint32 cols [MONO_METHOD_SIZE];
9831                 MonoMethod *method;
9832                 MonoMethodSignature *sig;
9833
9834                 /* klass->method.first points into the methodptr table */
9835                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9836
9837                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9838                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9839                         if (!method) {
9840                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9841                                 continue;
9842                         }
9843                         if (param_count == -1) {
9844                                 res = method;
9845                                 break;
9846                         }
9847                         sig = mono_method_signature_checked (method, &error);
9848                         if (!sig) {
9849                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9850                                 continue;
9851                         }
9852                         if (sig->param_count == param_count) {
9853                                 res = method;
9854                                 break;
9855                         }
9856                 }
9857         }
9858
9859         return res;
9860 }
9861
9862 /**
9863  * mono_class_get_method_from_name_flags:
9864  * @klass: where to look for the method
9865  * @name_space: name of the method
9866  * @param_count: number of parameters. -1 for any number.
9867  * @flags: flags which must be set in the method
9868  *
9869  * Obtains a MonoMethod with a given name and number of parameters.
9870  * It only works if there are no multiple signatures for any given method name.
9871  */
9872 MonoMethod *
9873 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9874 {
9875         MonoMethod *res = NULL;
9876         int i;
9877
9878         mono_class_init (klass);
9879
9880         if (klass->generic_class && !klass->methods) {
9881                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9882                 if (res) {
9883                         MonoError error;
9884                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9885                         if (!mono_error_ok (&error))
9886                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9887                 }
9888                 return res;
9889         }
9890
9891         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9892                 mono_class_setup_methods (klass);
9893                 /*
9894                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9895                 See mono/tests/array_load_exception.il
9896                 FIXME we should better report this error to the caller
9897                  */
9898                 if (!klass->methods)
9899                         return NULL;
9900                 for (i = 0; i < klass->method.count; ++i) {
9901                         MonoMethod *method = klass->methods [i];
9902
9903                         if (method->name[0] == name [0] && 
9904                                 !strcmp (name, method->name) &&
9905                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9906                                 ((method->flags & flags) == flags)) {
9907                                 res = method;
9908                                 break;
9909                         }
9910                 }
9911         }
9912         else {
9913             res = find_method_in_metadata (klass, name, param_count, flags);
9914         }
9915
9916         return res;
9917 }
9918
9919 /**
9920  * mono_class_set_failure:
9921  * @klass: class in which the failure was detected
9922  * @ex_type: the kind of exception/error to be thrown (later)
9923  * @ex_data: exception data (specific to each type of exception/error)
9924  *
9925  * Keep a detected failure informations in the class for later processing.
9926  * Note that only the first failure is kept.
9927  *
9928  * LOCKING: Acquires the loader lock.
9929  */
9930 gboolean
9931 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9932 {
9933         if (mono_class_has_failure (klass))
9934                 return FALSE;
9935
9936         mono_loader_lock ();
9937         klass->exception_type = ex_type;
9938         if (ex_data)
9939                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9940         mono_loader_unlock ();
9941
9942         return TRUE;
9943 }
9944
9945 /*
9946  * mono_class_get_exception_data:
9947  *
9948  *   Return the exception_data property of KLASS.
9949  *
9950  * LOCKING: Acquires the loader lock.
9951  */
9952 gpointer
9953 mono_class_get_exception_data (MonoClass *klass)
9954 {
9955         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9956 }
9957
9958 /**
9959  * mono_classes_init:
9960  *
9961  * Initialize the resources used by this module.
9962  */
9963 void
9964 mono_classes_init (void)
9965 {
9966         mono_os_mutex_init (&classes_mutex);
9967
9968         mono_counters_register ("Inflated methods size",
9969                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9970         mono_counters_register ("Inflated classes",
9971                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
9972         mono_counters_register ("Inflated classes size",
9973                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9974         mono_counters_register ("MonoClass size",
9975                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9976         mono_counters_register ("MonoClassExt size",
9977                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
9978 }
9979
9980 /**
9981  * mono_classes_cleanup:
9982  *
9983  * Free the resources used by this module.
9984  */
9985 void
9986 mono_classes_cleanup (void)
9987 {
9988         if (global_interface_bitset)
9989                 mono_bitset_free (global_interface_bitset);
9990         global_interface_bitset = NULL;
9991         mono_os_mutex_destroy (&classes_mutex);
9992 }
9993
9994 /**
9995  * mono_class_get_exception_for_failure:
9996  * @klass: class in which the failure was detected
9997  *
9998  * Return a constructed MonoException than the caller can then throw
9999  * using mono_raise_exception - or NULL if no failure is present (or
10000  * doesn't result in an exception).
10001  */
10002 MonoException*
10003 mono_class_get_exception_for_failure (MonoClass *klass)
10004 {
10005         gpointer exception_data = mono_class_get_exception_data (klass);
10006
10007         switch (mono_class_get_failure(klass)) {
10008         case MONO_EXCEPTION_TYPE_LOAD: {
10009                 MonoString *name;
10010                 MonoException *ex;
10011                 char *str = mono_type_get_full_name (klass);
10012                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10013                 name = mono_string_new (mono_domain_get (), str);
10014                 g_free (str);
10015                 ex = mono_get_exception_type_load (name, astr);
10016                 g_free (astr);
10017                 return ex;
10018         }
10019         case MONO_EXCEPTION_MISSING_METHOD: {
10020                 char *class_name = (char *)exception_data;
10021                 char *assembly_name = class_name + strlen (class_name) + 1;
10022
10023                 return mono_get_exception_missing_method (class_name, assembly_name);
10024         }
10025         case MONO_EXCEPTION_MISSING_FIELD: {
10026                 char *class_name = (char *)exception_data;
10027                 char *member_name = class_name + strlen (class_name) + 1;
10028
10029                 return mono_get_exception_missing_field (class_name, member_name);
10030         }
10031         case MONO_EXCEPTION_FILE_NOT_FOUND: {
10032                 char *msg_format = (char *)exception_data;
10033                 char *assembly_name = msg_format + strlen (msg_format) + 1;
10034                 char *msg = g_strdup_printf (msg_format, assembly_name);
10035                 MonoException *ex;
10036
10037                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10038
10039                 g_free (msg);
10040
10041                 return ex;
10042         }
10043         case MONO_EXCEPTION_BAD_IMAGE: {
10044                 return mono_get_exception_bad_image_format ((const char *)exception_data);
10045         }
10046         case MONO_EXCEPTION_INVALID_PROGRAM: {
10047                 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10048         }
10049         default: {
10050                 /* TODO - handle other class related failures */
10051                 return mono_get_exception_execution_engine ("Unknown class failure");
10052         }
10053         }
10054 }
10055
10056 static gboolean
10057 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10058  {
10059         outer_klass = mono_class_get_generic_type_definition (outer_klass);
10060         inner_klass = mono_class_get_generic_type_definition (inner_klass);
10061         do {
10062                 if (outer_klass == inner_klass)
10063                         return TRUE;
10064                 inner_klass = inner_klass->nested_in;
10065         } while (inner_klass);
10066         return FALSE;
10067 }
10068
10069 MonoClass *
10070 mono_class_get_generic_type_definition (MonoClass *klass)
10071 {
10072         return klass->generic_class ? klass->generic_class->container_class : klass;
10073 }
10074
10075 /*
10076  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10077  * 
10078  * Generic instantiations are ignored for all super types of @klass.
10079  * 
10080  * Visibility checks ignoring generic instantiations.  
10081  */
10082 gboolean
10083 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10084 {
10085         int i;
10086         klass = mono_class_get_generic_type_definition (klass);
10087         parent = mono_class_get_generic_type_definition (parent);
10088         mono_class_setup_supertypes (klass);
10089
10090         for (i = 0; i < klass->idepth; ++i) {
10091                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10092                         return TRUE;
10093         }
10094         return FALSE;
10095 }
10096 /*
10097  * Subtype can only access parent members with family protection if the site object
10098  * is subclass of Subtype. For example:
10099  * class A { protected int x; }
10100  * class B : A {
10101  *      void valid_access () {
10102  *              B b;
10103  *              b.x = 0;
10104  *  }
10105  *  void invalid_access () {
10106  *              A a;
10107  *              a.x = 0;
10108  *  }
10109  * }
10110  * */
10111 static gboolean
10112 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10113 {
10114         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10115                 return FALSE;
10116
10117         if (context_klass == NULL)
10118                 return TRUE;
10119         /*if access_klass is not member_klass context_klass must be type compat*/
10120         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10121                 return FALSE;
10122         return TRUE;
10123 }
10124
10125 static gboolean
10126 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10127 {
10128         GSList *tmp;
10129         if (accessing == accessed)
10130                 return TRUE;
10131         if (!accessed || !accessing)
10132                 return FALSE;
10133
10134         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10135          * anywhere so untrusted friends are not safe to access platform's code internals */
10136         if (mono_security_core_clr_enabled ()) {
10137                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10138                         return FALSE;
10139         }
10140
10141         mono_assembly_load_friends (accessed);
10142         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10143                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10144                 /* Be conservative with checks */
10145                 if (!friend_->name)
10146                         continue;
10147                 if (strcmp (accessing->aname.name, friend_->name))
10148                         continue;
10149                 if (friend_->public_key_token [0]) {
10150                         if (!accessing->aname.public_key_token [0])
10151                                 continue;
10152                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10153                                 continue;
10154                 }
10155                 return TRUE;
10156         }
10157         return FALSE;
10158 }
10159
10160 /*
10161  * If klass is a generic type or if it is derived from a generic type, return the
10162  * MonoClass of the generic definition
10163  * Returns NULL if not found
10164  */
10165 static MonoClass*
10166 get_generic_definition_class (MonoClass *klass)
10167 {
10168         while (klass) {
10169                 if (klass->generic_class && klass->generic_class->container_class)
10170                         return klass->generic_class->container_class;
10171                 klass = klass->parent;
10172         }
10173         return NULL;
10174 }
10175
10176 static gboolean
10177 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10178 {
10179         int i;
10180         for (i = 0; i < ginst->type_argc; ++i) {
10181                 MonoType *type = ginst->type_argv[i];
10182                 switch (type->type) {
10183                 case MONO_TYPE_SZARRAY:
10184                         if (!can_access_type (access_klass, type->data.klass))
10185                                 return FALSE;
10186                         break;
10187                 case MONO_TYPE_ARRAY:
10188                         if (!can_access_type (access_klass, type->data.array->eklass))
10189                                 return FALSE;
10190                         break;
10191                 case MONO_TYPE_PTR:
10192                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10193                                 return FALSE;
10194                         break;
10195                 case MONO_TYPE_CLASS:
10196                 case MONO_TYPE_VALUETYPE:
10197                 case MONO_TYPE_GENERICINST:
10198                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10199                                 return FALSE;
10200                 default:
10201                         break;
10202                 }
10203         }
10204         return TRUE;
10205 }
10206
10207 static gboolean
10208 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10209 {
10210         int access_level;
10211
10212         if (access_klass == member_klass)
10213                 return TRUE;
10214
10215         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10216                 return TRUE;
10217
10218         if (access_klass->element_class && !access_klass->enumtype)
10219                 access_klass = access_klass->element_class;
10220
10221         if (member_klass->element_class && !member_klass->enumtype)
10222                 member_klass = member_klass->element_class;
10223
10224         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10225
10226         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10227                 return TRUE;
10228
10229         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10230                 return FALSE;
10231
10232         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10233                 return TRUE;
10234
10235         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10236                 return FALSE;
10237
10238         /*Non nested type with nested visibility. We just fail it.*/
10239         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10240                 return FALSE;
10241
10242         switch (access_level) {
10243         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10244                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10245
10246         case TYPE_ATTRIBUTE_PUBLIC:
10247                 return TRUE;
10248
10249         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10250                 return TRUE;
10251
10252         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10253                 return is_nesting_type (member_klass, access_klass);
10254
10255         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10256                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10257
10258         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10259                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10260
10261         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10262                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10263                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10264
10265         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10266                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10267                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10268         }
10269         return FALSE;
10270 }
10271
10272 /* FIXME: check visibility of type, too */
10273 static gboolean
10274 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10275 {
10276         MonoClass *member_generic_def;
10277         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10278                 return TRUE;
10279
10280         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10281                                         access_klass->generic_container) && 
10282                         (member_generic_def = get_generic_definition_class (member_klass))) {
10283                 MonoClass *access_container;
10284
10285                 if (access_klass->generic_container)
10286                         access_container = access_klass;
10287                 else
10288                         access_container = access_klass->generic_class->container_class;
10289
10290                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10291                         return TRUE;
10292         }
10293
10294         /* Partition I 8.5.3.2 */
10295         /* the access level values are the same for fields and methods */
10296         switch (access_level) {
10297         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10298                 /* same compilation unit */
10299                 return access_klass->image == member_klass->image;
10300         case FIELD_ATTRIBUTE_PRIVATE:
10301                 return access_klass == member_klass;
10302         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10303                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10304                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10305                         return TRUE;
10306                 return FALSE;
10307         case FIELD_ATTRIBUTE_ASSEMBLY:
10308                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10309         case FIELD_ATTRIBUTE_FAMILY:
10310                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10311                         return TRUE;
10312                 return FALSE;
10313         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10314                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10315                         return TRUE;
10316                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10317         case FIELD_ATTRIBUTE_PUBLIC:
10318                 return TRUE;
10319         }
10320         return FALSE;
10321 }
10322
10323 /**
10324  * mono_method_can_access_field:
10325  * @method: Method that will attempt to access the field
10326  * @field: the field to access
10327  *
10328  * Used to determine if a method is allowed to access the specified field.
10329  *
10330  * Returns: TRUE if the given @method is allowed to access the @field while following
10331  * the accessibility rules of the CLI.
10332  */
10333 gboolean
10334 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10335 {
10336         /* FIXME: check all overlapping fields */
10337         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10338         if (!can) {
10339                 MonoClass *nested = method->klass->nested_in;
10340                 while (nested) {
10341                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10342                         if (can)
10343                                 return TRUE;
10344                         nested = nested->nested_in;
10345                 }
10346         }
10347         return can;
10348 }
10349
10350 /**
10351  * mono_method_can_access_method:
10352  * @method: Method that will attempt to access the other method
10353  * @called: the method that we want to probe for accessibility.
10354  *
10355  * Used to determine if the @method is allowed to access the specified @called method.
10356  *
10357  * Returns: TRUE if the given @method is allowed to invoke the @called while following
10358  * the accessibility rules of the CLI.
10359  */
10360 gboolean
10361 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10362 {
10363         method = mono_method_get_method_definition (method);
10364         called = mono_method_get_method_definition (called);
10365         return mono_method_can_access_method_full (method, called, NULL);
10366 }
10367
10368 /*
10369  * mono_method_can_access_method_full:
10370  * @method: The caller method 
10371  * @called: The called method 
10372  * @context_klass: The static type on stack of the owner @called object used
10373  * 
10374  * This function must be used with instance calls, as they have more strict family accessibility.
10375  * It can be used with static methods, but context_klass should be NULL.
10376  * 
10377  * Returns: TRUE if caller have proper visibility and acessibility to @called
10378  */
10379 gboolean
10380 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10381 {
10382         /* Wrappers are except from access checks */
10383         if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10384                 return TRUE;
10385
10386         MonoClass *access_class = method->klass;
10387         MonoClass *member_class = called->klass;
10388         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10389         if (!can) {
10390                 MonoClass *nested = access_class->nested_in;
10391                 while (nested) {
10392                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10393                         if (can)
10394                                 break;
10395                         nested = nested->nested_in;
10396                 }
10397         }
10398
10399         if (!can)
10400                 return FALSE;
10401
10402         can = can_access_type (access_class, member_class);
10403         if (!can) {
10404                 MonoClass *nested = access_class->nested_in;
10405                 while (nested) {
10406                         can = can_access_type (nested, member_class);
10407                         if (can)
10408                                 break;
10409                         nested = nested->nested_in;
10410                 }
10411         }
10412
10413         if (!can)
10414                 return FALSE;
10415
10416         if (called->is_inflated) {
10417                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10418                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10419                         return FALSE;
10420         }
10421                 
10422         return TRUE;
10423 }
10424
10425
10426 /*
10427  * mono_method_can_access_field_full:
10428  * @method: The caller method 
10429  * @field: The accessed field
10430  * @context_klass: The static type on stack of the owner @field object used
10431  * 
10432  * This function must be used with instance fields, as they have more strict family accessibility.
10433  * It can be used with static fields, but context_klass should be NULL.
10434  * 
10435  * Returns: TRUE if caller have proper visibility and acessibility to @field
10436  */
10437 gboolean
10438 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10439 {
10440         MonoClass *access_class = method->klass;
10441         MonoClass *member_class = field->parent;
10442         /* FIXME: check all overlapping fields */
10443         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10444         if (!can) {
10445                 MonoClass *nested = access_class->nested_in;
10446                 while (nested) {
10447                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10448                         if (can)
10449                                 break;
10450                         nested = nested->nested_in;
10451                 }
10452         }
10453
10454         if (!can)
10455                 return FALSE;
10456
10457         can = can_access_type (access_class, member_class);
10458         if (!can) {
10459                 MonoClass *nested = access_class->nested_in;
10460                 while (nested) {
10461                         can = can_access_type (nested, member_class);
10462                         if (can)
10463                                 break;
10464                         nested = nested->nested_in;
10465                 }
10466         }
10467
10468         if (!can)
10469                 return FALSE;
10470         return TRUE;
10471 }
10472
10473 /*
10474  * mono_class_can_access_class:
10475  * @source_class: The source class 
10476  * @target_class: The accessed class
10477  * 
10478  * This function returns is @target_class is visible to @source_class
10479  * 
10480  * Returns: TRUE if source have proper visibility and acessibility to target
10481  */
10482 gboolean
10483 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10484 {
10485         return can_access_type (source_class, target_class);
10486 }
10487
10488 /**
10489  * mono_type_is_valid_enum_basetype:
10490  * @type: The MonoType to check
10491  *
10492  * Returns: TRUE if the type can be used as the basetype of an enum
10493  */
10494 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10495         switch (type->type) {
10496         case MONO_TYPE_I1:
10497         case MONO_TYPE_U1:
10498         case MONO_TYPE_BOOLEAN:
10499         case MONO_TYPE_I2:
10500         case MONO_TYPE_U2:
10501         case MONO_TYPE_CHAR:
10502         case MONO_TYPE_I4:
10503         case MONO_TYPE_U4:
10504         case MONO_TYPE_I8:
10505         case MONO_TYPE_U8:
10506         case MONO_TYPE_I:
10507         case MONO_TYPE_U:
10508                 return TRUE;
10509         default:
10510                 return FALSE;
10511         }
10512 }
10513
10514 /**
10515  * mono_class_is_valid_enum:
10516  * @klass: An enum class to be validated
10517  *
10518  * This method verify the required properties an enum should have.
10519  *  
10520  * Returns: TRUE if the informed enum class is valid 
10521  *
10522  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10523  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10524  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10525  */
10526 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10527         MonoClassField * field;
10528         gpointer iter = NULL;
10529         gboolean found_base_field = FALSE;
10530
10531         g_assert (klass->enumtype);
10532         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10533         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10534                 return FALSE;
10535         }
10536
10537         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10538                 return FALSE;
10539
10540         while ((field = mono_class_get_fields (klass, &iter))) {
10541                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10542                         if (found_base_field)
10543                                 return FALSE;
10544                         found_base_field = TRUE;
10545                         if (!mono_type_is_valid_enum_basetype (field->type))
10546                                 return FALSE;
10547                 }
10548         }
10549
10550         if (!found_base_field)
10551                 return FALSE;
10552
10553         if (klass->method.count > 0) 
10554                 return FALSE;
10555
10556         return TRUE;
10557 }
10558
10559 gboolean
10560 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10561 {
10562         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10563 }
10564
10565 /*
10566  * mono_class_setup_interface_id:
10567  *
10568  * Initializes MonoClass::interface_id if required.
10569  *
10570  * LOCKING: Acquires the loader lock.
10571  */
10572 void
10573 mono_class_setup_interface_id (MonoClass *klass)
10574 {
10575         mono_loader_lock ();
10576         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10577                 klass->interface_id = mono_get_unique_iid (klass);
10578         mono_loader_unlock ();
10579 }
10580
10581 /*
10582  * mono_class_alloc_ext:
10583  *
10584  *   Allocate klass->ext if not already done.
10585  */
10586 void
10587 mono_class_alloc_ext (MonoClass *klass)
10588 {
10589         MonoClassExt *ext;
10590
10591         if (klass->ext)
10592                 return;
10593
10594         ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10595         mono_image_lock (klass->image);
10596         mono_memory_barrier ();
10597         if (!klass->ext)
10598                 klass->ext = ext;
10599         class_ext_size += sizeof (MonoClassExt);
10600         mono_image_unlock (klass->image);
10601 }
10602
10603 /*
10604  * mono_class_setup_interfaces:
10605  *
10606  *   Initialize klass->interfaces/interfaces_count.
10607  * LOCKING: Acquires the loader lock.
10608  * This function can fail the type.
10609  */
10610 void
10611 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10612 {
10613         int i, interface_count;
10614         MonoClass **interfaces;
10615
10616         mono_error_init (error);
10617
10618         if (klass->interfaces_inited)
10619                 return;
10620
10621         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10622                 MonoType *args [1];
10623
10624                 /* generic IList, ICollection, IEnumerable */
10625                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10626                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10627
10628                 args [0] = &klass->element_class->byval_arg;
10629                 interfaces [0] = mono_class_bind_generic_parameters (
10630                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10631                 if (interface_count > 1)
10632                         interfaces [1] = mono_class_bind_generic_parameters (
10633                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10634         } else if (klass->generic_class) {
10635                 MonoClass *gklass = klass->generic_class->container_class;
10636
10637                 mono_class_setup_interfaces (gklass, error);
10638                 if (!mono_error_ok (error)) {
10639                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10640                         return;
10641                 }
10642
10643                 interface_count = gklass->interface_count;
10644                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10645                 for (i = 0; i < interface_count; i++) {
10646                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10647                         if (!mono_error_ok (error)) {
10648                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10649                                 return;
10650                         }
10651                 }
10652         } else {
10653                 interface_count = 0;
10654                 interfaces = NULL;
10655         }
10656
10657         mono_image_lock (klass->image);
10658
10659         if (!klass->interfaces_inited) {
10660                 klass->interface_count = interface_count;
10661                 klass->interfaces = interfaces;
10662
10663                 mono_memory_barrier ();
10664
10665                 klass->interfaces_inited = TRUE;
10666         }
10667
10668         mono_image_unlock (klass->image);
10669 }
10670
10671 static void
10672 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10673 {
10674         MonoClass *klass = field->parent;
10675         MonoImage *image = klass->image;
10676         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10677         int field_idx = field - klass->fields;
10678
10679         mono_error_init (error);
10680
10681         if (gtd) {
10682                 MonoClassField *gfield = &gtd->fields [field_idx];
10683                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10684                 if (!mono_error_ok (error)) {
10685                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10686                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10687                 }
10688
10689                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10690                 if (!mono_error_ok (error)) {
10691                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10692                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10693                 }
10694         } else {
10695                 const char *sig;
10696                 guint32 cols [MONO_FIELD_SIZE];
10697                 MonoGenericContainer *container = NULL;
10698                 int idx = klass->field.first + field_idx;
10699
10700                 /*FIXME, in theory we do not lazy load SRE fields*/
10701                 g_assert (!image_is_dynamic (image));
10702
10703                 if (klass->generic_container) {
10704                         container = klass->generic_container;
10705                 } else if (gtd) {
10706                         container = gtd->generic_container;
10707                         g_assert (container);
10708                 }
10709
10710                 /* klass->field.first and idx points into the fieldptr table */
10711                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10712
10713                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10714                         mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10715                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10716                         return;
10717                 }
10718
10719                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10720
10721                 mono_metadata_decode_value (sig, &sig);
10722                 /* FIELD signature == 0x06 */
10723                 g_assert (*sig == 0x06);
10724
10725                 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10726                 if (!field->type) {
10727                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10728                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10729                 }
10730         }
10731 }
10732
10733 static guint32
10734 mono_field_resolve_flags (MonoClassField *field)
10735 {
10736         MonoClass *klass = field->parent;
10737         MonoImage *image = klass->image;
10738         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10739         int field_idx = field - klass->fields;
10740
10741
10742         if (gtd) {
10743                 MonoClassField *gfield = &gtd->fields [field_idx];
10744                 return mono_field_get_flags (gfield);
10745         } else {
10746                 int idx = klass->field.first + field_idx;
10747
10748                 /*FIXME, in theory we do not lazy load SRE fields*/
10749                 g_assert (!image_is_dynamic (image));
10750
10751                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10752         }
10753 }
10754
10755 /**
10756  * mono_class_setup_basic_field_info:
10757  * @class: The class to initialize
10758  *
10759  * Initializes the klass->fields array of fields.
10760  * Aquires the loader lock.
10761  */
10762 static void
10763 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10764 {
10765         mono_loader_lock ();
10766         mono_class_setup_basic_field_info (klass);
10767         mono_loader_unlock ();
10768 }
10769
10770 /**
10771  * mono_class_get_fields_lazy:
10772  * @klass: the MonoClass to act on
10773  *
10774  * This routine is an iterator routine for retrieving the fields in a class.
10775  * Only minimal information about fields are loaded. Accessors must be used
10776  * for all MonoClassField returned.
10777  *
10778  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10779  * iterate over all of the elements.  When no more values are
10780  * available, the return value is NULL.
10781  *
10782  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10783  */
10784 MonoClassField*
10785 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10786 {
10787         MonoClassField* field;
10788         if (!iter)
10789                 return NULL;
10790         if (!*iter) {
10791                 mono_class_setup_basic_field_info_locking (klass);
10792                 if (!klass->fields)
10793                         return NULL;
10794                 /* start from the first */
10795                 if (klass->field.count) {
10796                         *iter = &klass->fields [0];
10797                         return (MonoClassField *)*iter;
10798                 } else {
10799                         /* no fields */
10800                         return NULL;
10801                 }
10802         }
10803         field = (MonoClassField *)*iter;
10804         field++;
10805         if (field < &klass->fields [klass->field.count]) {
10806                 *iter = field;
10807                 return (MonoClassField *)*iter;
10808         }
10809         return NULL;
10810 }
10811
10812 char*
10813 mono_class_full_name (MonoClass *klass)
10814 {
10815         return mono_type_full_name (&klass->byval_arg);
10816 }
10817
10818 /* Declare all shared lazy type lookup functions */
10819 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)