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