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