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