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