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