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