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