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