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