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