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