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