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