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