[runtime] Add an assert to mono_class_setup_vtable_general () to catch cases when...
[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         g_assert (cur_slot <= max_vtsize);
4541
4542         /* Ensure that all vtable slots are filled with concrete instance methods */
4543         if (!mono_class_is_abstract (klass)) {
4544                 for (i = 0; i < cur_slot; ++i) {
4545                         if (vtable [i] == NULL || (vtable [i]->flags & (METHOD_ATTRIBUTE_ABSTRACT | METHOD_ATTRIBUTE_STATIC))) {
4546                                 char *type_name = mono_type_get_full_name (klass);
4547                                 char *method_name = vtable [i] ? mono_method_full_name (vtable [i], TRUE) : g_strdup ("none");
4548                                 mono_class_set_type_load_failure (klass, "Type %s has invalid vtable method slot %d with method %s", type_name, i, method_name);
4549                                 g_free (type_name);
4550                                 g_free (method_name);
4551                                 g_free (vtable);
4552                                 return;
4553                         }
4554                 }
4555         }
4556
4557         if (mono_class_is_ginst (klass)) {
4558                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4559
4560                 mono_class_init (gklass);
4561
4562                 klass->vtable_size = MAX (gklass->vtable_size, cur_slot);
4563         } else {
4564                 /* Check that the vtable_size value computed in mono_class_init () is correct */
4565                 if (klass->vtable_size)
4566                         g_assert (cur_slot == klass->vtable_size);
4567                 klass->vtable_size = cur_slot;
4568         }
4569
4570         /* Try to share the vtable with our parent. */
4571         if (klass->parent && (klass->parent->vtable_size == klass->vtable_size) && (memcmp (klass->parent->vtable, vtable, sizeof (gpointer) * klass->vtable_size) == 0)) {
4572                 mono_memory_barrier ();
4573                 klass->vtable = klass->parent->vtable;
4574         } else {
4575                 MonoMethod **tmp = (MonoMethod **)mono_class_alloc0 (klass, sizeof (gpointer) * klass->vtable_size);
4576                 memcpy (tmp, vtable,  sizeof (gpointer) * klass->vtable_size);
4577                 mono_memory_barrier ();
4578                 klass->vtable = tmp;
4579         }
4580
4581         DEBUG_INTERFACE_VTABLE (print_vtable_full (klass, klass->vtable, klass->vtable_size, first_non_interface_slot, "FINALLY", FALSE));
4582         if (mono_print_vtable) {
4583                 int icount = 0;
4584
4585                 print_implemented_interfaces (klass);
4586                 
4587                 for (i = 0; i <= max_iid; i++)
4588                         if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, i))
4589                                 icount++;
4590
4591                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&klass->byval_arg),
4592                         klass->vtable_size, icount);
4593
4594                 for (i = 0; i < cur_slot; ++i) {
4595                         MonoMethod *cm;
4596                
4597                         cm = vtable [i];
4598                         if (cm) {
4599                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
4600                                         mono_method_full_name (cm, TRUE));
4601                         }
4602                 }
4603
4604
4605                 if (icount) {
4606                         printf ("Interfaces %s.%s (max_iid = %d)\n", klass->name_space,
4607                                 klass->name, max_iid);
4608         
4609                         for (i = 0; i < klass->interface_count; i++) {
4610                                 ic = klass->interfaces [i];
4611                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4612                                         mono_class_interface_offset (klass, ic),
4613                                         count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4614                         }
4615
4616                         for (k = klass->parent; k ; k = k->parent) {
4617                                 for (i = 0; i < k->interface_count; i++) {
4618                                         ic = k->interfaces [i]; 
4619                                         printf ("  parent slot offset: %03d, method count: %03d, iid: %03d %s\n",  
4620                                                 mono_class_interface_offset (klass, ic),
4621                                                 count_virtual_methods (ic), ic->interface_id, mono_type_full_name (&ic->byval_arg));
4622                                 }
4623                         }
4624                 }
4625         }
4626
4627         g_free (vtable);
4628
4629         VERIFY_INTERFACE_VTABLE (mono_class_verify_vtable (klass));
4630         return;
4631
4632 fail:
4633         {
4634         char *name = mono_type_get_full_name (klass);
4635         mono_class_set_type_load_failure (klass, "VTable setup of type %s failed", name);
4636         g_free (name);
4637         g_free (vtable);
4638         if (override_map)
4639                 g_hash_table_destroy (override_map);
4640         if (virt_methods)
4641                 g_slist_free (virt_methods);
4642         }
4643 }
4644
4645 /*
4646  * mono_method_get_vtable_slot:
4647  *
4648  *   Returns method->slot, computing it if neccesary. Return -1 on failure.
4649  * LOCKING: Acquires the loader lock.
4650  *
4651  * FIXME Use proper MonoError machinery here.
4652  */
4653 int
4654 mono_method_get_vtable_slot (MonoMethod *method)
4655 {
4656         if (method->slot == -1) {
4657                 mono_class_setup_vtable (method->klass);
4658                 if (mono_class_has_failure (method->klass))
4659                         return -1;
4660                 if (method->slot == -1) {
4661                         MonoClass *gklass;
4662                         int i, mcount;
4663
4664                         if (!mono_class_is_ginst (method->klass)) {
4665                                 g_assert (method->is_inflated);
4666                                 return mono_method_get_vtable_slot (((MonoMethodInflated*)method)->declaring);
4667                         }
4668
4669                         /* This can happen for abstract methods of generic instances due to the shortcut code in mono_class_setup_vtable_general (). */
4670                         g_assert (mono_class_is_ginst (method->klass));
4671                         gklass = mono_class_get_generic_class (method->klass)->container_class;
4672                         mono_class_setup_methods (method->klass);
4673                         g_assert (method->klass->methods);
4674                         mcount = mono_class_get_method_count (method->klass);
4675                         for (i = 0; i < mcount; ++i) {
4676                                 if (method->klass->methods [i] == method)
4677                                         break;
4678                         }
4679                         g_assert (i < mcount);
4680                         g_assert (gklass->methods);
4681                         method->slot = gklass->methods [i]->slot;
4682                 }
4683                 g_assert (method->slot != -1);
4684         }
4685         return method->slot;
4686 }
4687
4688 /**
4689  * mono_method_get_vtable_index:
4690  * @method: a method
4691  *
4692  * Returns the index into the runtime vtable to access the method or,
4693  * in the case of a virtual generic method, the virtual generic method
4694  * thunk. Returns -1 on failure.
4695  *
4696  * FIXME Use proper MonoError machinery here.
4697  */
4698 int
4699 mono_method_get_vtable_index (MonoMethod *method)
4700 {
4701         if (method->is_inflated && (method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
4702                 MonoMethodInflated *imethod = (MonoMethodInflated*)method;
4703                 if (imethod->declaring->is_generic)
4704                         return mono_method_get_vtable_slot (imethod->declaring);
4705         }
4706         return mono_method_get_vtable_slot (method);
4707 }
4708
4709 static MonoMethod *default_ghc = NULL;
4710 static MonoMethod *default_finalize = NULL;
4711 static int finalize_slot = -1;
4712 static int ghc_slot = -1;
4713
4714 static void
4715 initialize_object_slots (MonoClass *klass)
4716 {
4717         int i;
4718         if (default_ghc)
4719                 return;
4720         if (klass == mono_defaults.object_class) {
4721                 mono_class_setup_vtable (klass);
4722                 for (i = 0; i < klass->vtable_size; ++i) {
4723                         MonoMethod *cm = klass->vtable [i];
4724        
4725                         if (!strcmp (cm->name, "GetHashCode"))
4726                                 ghc_slot = i;
4727                         else if (!strcmp (cm->name, "Finalize"))
4728                                 finalize_slot = i;
4729                 }
4730
4731                 g_assert (ghc_slot > 0);
4732                 default_ghc = klass->vtable [ghc_slot];
4733
4734                 g_assert (finalize_slot > 0);
4735                 default_finalize = klass->vtable [finalize_slot];
4736         }
4737 }
4738
4739 typedef struct {
4740         MonoMethod *array_method;
4741         char *name;
4742 } GenericArrayMethodInfo;
4743
4744 static int generic_array_method_num = 0;
4745 static GenericArrayMethodInfo *generic_array_method_info = NULL;
4746
4747 static int
4748 generic_array_methods (MonoClass *klass)
4749 {
4750         int i, count_generic = 0, mcount;
4751         GList *list = NULL, *tmp;
4752         if (generic_array_method_num)
4753                 return generic_array_method_num;
4754         mono_class_setup_methods (klass->parent); /*This is setting up System.Array*/
4755         g_assert (!mono_class_has_failure (klass->parent)); /*So hitting this assert is a huge problem*/
4756         mcount = mono_class_get_method_count (klass->parent);
4757         for (i = 0; i < mcount; i++) {
4758                 MonoMethod *m = klass->parent->methods [i];
4759                 if (!strncmp (m->name, "InternalArray__", 15)) {
4760                         count_generic++;
4761                         list = g_list_prepend (list, m);
4762                 }
4763         }
4764         list = g_list_reverse (list);
4765         generic_array_method_info = (GenericArrayMethodInfo *)mono_image_alloc (mono_defaults.corlib, sizeof (GenericArrayMethodInfo) * count_generic);
4766         i = 0;
4767         for (tmp = list; tmp; tmp = tmp->next) {
4768                 const char *mname, *iname;
4769                 gchar *name;
4770                 MonoMethod *m = (MonoMethod *)tmp->data;
4771                 const char *ireadonlylist_prefix = "InternalArray__IReadOnlyList_";
4772                 const char *ireadonlycollection_prefix = "InternalArray__IReadOnlyCollection_";
4773
4774                 generic_array_method_info [i].array_method = m;
4775                 if (!strncmp (m->name, "InternalArray__ICollection_", 27)) {
4776                         iname = "System.Collections.Generic.ICollection`1.";
4777                         mname = m->name + 27;
4778                 } else if (!strncmp (m->name, "InternalArray__IEnumerable_", 27)) {
4779                         iname = "System.Collections.Generic.IEnumerable`1.";
4780                         mname = m->name + 27;
4781                 } else if (!strncmp (m->name, ireadonlylist_prefix, strlen (ireadonlylist_prefix))) {
4782                         iname = "System.Collections.Generic.IReadOnlyList`1.";
4783                         mname = m->name + strlen (ireadonlylist_prefix);
4784                 } else if (!strncmp (m->name, ireadonlycollection_prefix, strlen (ireadonlycollection_prefix))) {
4785                         iname = "System.Collections.Generic.IReadOnlyCollection`1.";
4786                         mname = m->name + strlen (ireadonlycollection_prefix);
4787                 } else if (!strncmp (m->name, "InternalArray__", 15)) {
4788                         iname = "System.Collections.Generic.IList`1.";
4789                         mname = m->name + 15;
4790                 } else {
4791                         g_assert_not_reached ();
4792                 }
4793
4794                 name = (gchar *)mono_image_alloc (mono_defaults.corlib, strlen (iname) + strlen (mname) + 1);
4795                 strcpy (name, iname);
4796                 strcpy (name + strlen (iname), mname);
4797                 generic_array_method_info [i].name = name;
4798                 i++;
4799         }
4800         /*g_print ("array generic methods: %d\n", count_generic);*/
4801
4802         generic_array_method_num = count_generic;
4803         g_list_free (list);
4804         return generic_array_method_num;
4805 }
4806
4807 static void
4808 setup_generic_array_ifaces (MonoClass *klass, MonoClass *iface, MonoMethod **methods, int pos)
4809 {
4810         MonoGenericContext tmp_context;
4811         int i;
4812
4813         tmp_context.class_inst = NULL;
4814         tmp_context.method_inst = mono_class_get_generic_class (iface)->context.class_inst;
4815         //g_print ("setting up array interface: %s\n", mono_type_get_name_full (&iface->byval_arg, 0));
4816
4817         for (i = 0; i < generic_array_method_num; i++) {
4818                 MonoError error;
4819                 MonoMethod *m = generic_array_method_info [i].array_method;
4820                 MonoMethod *inflated;
4821
4822                 inflated = mono_class_inflate_generic_method_checked (m, &tmp_context, &error);
4823                 g_assert (mono_error_ok (&error)); /*FIXME proper error handling*/
4824                 methods [pos++] = mono_marshal_get_generic_array_helper (klass, iface, generic_array_method_info [i].name, inflated);
4825         }
4826 }
4827
4828 static char*
4829 concat_two_strings_with_zero (MonoImage *image, const char *s1, const char *s2)
4830 {
4831         int null_length = strlen ("(null)");
4832         int len = (s1 ? strlen (s1) : null_length) + (s2 ? strlen (s2) : null_length) + 2;
4833         char *s = (char *)mono_image_alloc (image, len);
4834         int result;
4835
4836         result = g_snprintf (s, len, "%s%c%s", s1 ? s1 : "(null)", '\0', s2 ? s2 : "(null)");
4837         g_assert (result == len - 1);
4838
4839         return s;
4840 }
4841
4842 /**
4843  * mono_class_init:
4844  * @klass: the class to initialize
4845  *
4846  *   Compute the instance_size, class_size and other infos that cannot be 
4847  * computed at mono_class_get() time. Also compute vtable_size if possible. 
4848  * Returns TRUE on success or FALSE if there was a problem in loading
4849  * the type (incorrect assemblies, missing assemblies, methods, etc).
4850  * Initializes the following fields in @klass:
4851  * - all the fields initialized by mono_class_init_sizes ()
4852  * - has_cctor
4853  * - ghcimpl
4854  * - inited
4855  *
4856  * LOCKING: Acquires the loader lock.
4857  */
4858 gboolean
4859 mono_class_init (MonoClass *klass)
4860 {
4861         int i, vtable_size = 0, array_method_count = 0;
4862         MonoCachedClassInfo cached_info;
4863         gboolean has_cached_info;
4864         gboolean locked = FALSE;
4865         gboolean ghcimpl = FALSE;
4866         gboolean has_cctor = FALSE;
4867         int first_iface_slot = 0;
4868         
4869         g_assert (klass);
4870
4871         /* Double-checking locking pattern */
4872         if (klass->inited || mono_class_has_failure (klass))
4873                 return !mono_class_has_failure (klass);
4874
4875         /*g_print ("Init class %s\n", mono_type_get_full_name (klass));*/
4876
4877         /*
4878          * This function can recursively call itself.
4879          */
4880         GSList *init_list = (GSList *)mono_native_tls_get_value (init_pending_tls_id);
4881         if (g_slist_find (init_list, klass)) {
4882                 mono_class_set_type_load_failure (klass, "Recursive type definition detected");
4883                 goto leave;
4884         }
4885         init_list = g_slist_prepend (init_list, klass);
4886         mono_native_tls_set_value (init_pending_tls_id, init_list);
4887
4888         /*
4889          * We want to avoid doing complicated work inside locks, so we compute all the required
4890          * information and write it to @klass inside a lock.
4891          */
4892
4893         if (mono_verifier_is_enabled_for_class (klass) && !mono_verifier_verify_class (klass)) {
4894                 mono_class_set_type_load_failure (klass, "%s", concat_two_strings_with_zero (klass->image, klass->name, klass->image->assembly_name));
4895                 goto leave;
4896         }
4897
4898         if (klass->byval_arg.type == MONO_TYPE_ARRAY || klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4899                 MonoClass *element_class = klass->element_class;
4900                 if (!element_class->inited) 
4901                         mono_class_init (element_class);
4902                 if (mono_class_set_type_load_failure_causedby_class (klass, element_class, "Could not load array element class"))
4903                         goto leave;
4904         }
4905
4906         mono_stats.initialized_class_count++;
4907
4908         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic) {
4909                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4910
4911                 mono_class_init (gklass);
4912                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic Type Definition failed to init"))
4913                         goto leave;
4914
4915                 mono_class_setup_interface_id (klass);
4916         }
4917
4918         if (klass->parent && !klass->parent->inited)
4919                 mono_class_init (klass->parent);
4920
4921         has_cached_info = mono_class_get_cached_class_info (klass, &cached_info);
4922
4923         /* Compute instance size etc. */
4924         init_sizes_with_info (klass, has_cached_info ? &cached_info : NULL);
4925         if (mono_class_has_failure (klass))
4926                 goto leave;
4927
4928         mono_class_setup_supertypes (klass);
4929
4930         if (!default_ghc)
4931                 initialize_object_slots (klass);
4932
4933         /* 
4934          * Initialize the rest of the data without creating a generic vtable if possible.
4935          * If possible, also compute vtable_size, so mono_class_create_runtime_vtable () can
4936          * also avoid computing a generic vtable.
4937          */
4938         if (has_cached_info) {
4939                 /* AOT case */
4940                 vtable_size = cached_info.vtable_size;
4941                 ghcimpl = cached_info.ghcimpl;
4942                 has_cctor = cached_info.has_cctor;
4943         } else if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
4944                 /* SZARRAY can have 2 vtable layouts, with and without the stelemref method.
4945                  * The first slot if for array with.
4946                  */
4947                 static int szarray_vtable_size[2] = { 0 };
4948
4949                 int slot = MONO_TYPE_IS_REFERENCE (&klass->element_class->byval_arg) ? 0 : 1;
4950
4951                 /* SZARRAY case */
4952                 if (!szarray_vtable_size [slot]) {
4953                         mono_class_setup_vtable (klass);
4954                         szarray_vtable_size [slot] = klass->vtable_size;
4955                         vtable_size = klass->vtable_size;
4956                 } else {
4957                         vtable_size = szarray_vtable_size[slot];
4958                 }
4959         } else if (mono_class_is_ginst (klass) && !MONO_CLASS_IS_INTERFACE (klass)) {
4960                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4961
4962                 /* Generic instance case */
4963                 ghcimpl = gklass->ghcimpl;
4964                 has_cctor = gklass->has_cctor;
4965
4966                 mono_class_setup_vtable (gklass);
4967                 if (mono_class_set_type_load_failure_causedby_class (klass, gklass, "Generic type definition failed to init"))
4968                         goto leave;
4969
4970                 vtable_size = gklass->vtable_size;
4971         } else {
4972                 /* General case */
4973
4974                 /* ghcimpl is not currently used
4975                 klass->ghcimpl = 1;
4976                 if (klass->parent) {
4977                         MonoMethod *cmethod = klass->vtable [ghc_slot];
4978                         if (cmethod->is_inflated)
4979                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
4980                         if (cmethod == default_ghc) {
4981                                 klass->ghcimpl = 0;
4982                         }
4983                 }
4984                 */
4985
4986                 /* C# doesn't allow interfaces to have cctors */
4987                 if (!MONO_CLASS_IS_INTERFACE (klass) || klass->image != mono_defaults.corlib) {
4988                         MonoMethod *cmethod = NULL;
4989
4990                         if (mono_class_is_ginst (klass)) {
4991                                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
4992
4993                                 /* Generic instance case */
4994                                 ghcimpl = gklass->ghcimpl;
4995                                 has_cctor = gklass->has_cctor;
4996                         } else if (klass->type_token && !image_is_dynamic(klass->image)) {
4997                                 cmethod = find_method_in_metadata (klass, ".cctor", 0, METHOD_ATTRIBUTE_SPECIAL_NAME);
4998                                 /* The find_method function ignores the 'flags' argument */
4999                                 if (cmethod && (cmethod->flags & METHOD_ATTRIBUTE_SPECIAL_NAME))
5000                                         has_cctor = 1;
5001                         } else {
5002                                 mono_class_setup_methods (klass);
5003                                 if (mono_class_has_failure (klass))
5004                                         goto leave;
5005
5006                                 int mcount = mono_class_get_method_count (klass);
5007                                 for (i = 0; i < mcount; ++i) {
5008                                         MonoMethod *method = klass->methods [i];
5009                                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
5010                                                 (strcmp (".cctor", method->name) == 0)) {
5011                                                 has_cctor = 1;
5012                                                 break;
5013                                         }
5014                                 }
5015                         }
5016                 }
5017         }
5018
5019         if (klass->rank) {
5020                 array_method_count = 3 + (klass->rank > 1? 2: 1);
5021
5022                 if (klass->interface_count) {
5023                         int count_generic = generic_array_methods (klass);
5024                         array_method_count += klass->interface_count * count_generic;
5025                 }
5026         }
5027
5028         if (klass->parent) {
5029                 if (!klass->parent->vtable_size)
5030                         mono_class_setup_vtable (klass->parent);
5031                 if (mono_class_set_type_load_failure_causedby_class (klass, klass->parent, "Parent class vtable failed to initialize"))
5032                         goto leave;
5033                 g_assert (klass->parent->vtable_size);
5034                 first_iface_slot = klass->parent->vtable_size;
5035                 if (mono_class_need_stelemref_method (klass))
5036                         ++first_iface_slot;
5037         }
5038
5039         /*
5040          * Do the actual changes to @klass inside the loader lock
5041          */
5042         mono_loader_lock ();
5043         locked = TRUE;
5044
5045         if (klass->inited || mono_class_has_failure (klass)) {
5046                 mono_loader_unlock ();
5047                 /* Somebody might have gotten in before us */
5048                 return !mono_class_has_failure (klass);
5049         }
5050
5051         mono_stats.initialized_class_count++;
5052
5053         if (mono_class_is_ginst (klass) && !mono_class_get_generic_class (klass)->is_dynamic)
5054                 mono_stats.generic_class_count++;
5055
5056         if (mono_class_is_ginst (klass) || image_is_dynamic (klass->image) || !klass->type_token || (has_cached_info && !cached_info.has_nested_classes))
5057                 klass->nested_classes_inited = TRUE;
5058         klass->ghcimpl = ghcimpl;
5059         klass->has_cctor = has_cctor;
5060         if (vtable_size)
5061                 klass->vtable_size = vtable_size;
5062         if (has_cached_info) {
5063                 klass->has_finalize = cached_info.has_finalize;
5064                 klass->has_finalize_inited = TRUE;
5065         }
5066         if (klass->rank)
5067                 mono_class_set_method_count (klass, array_method_count);
5068
5069         mono_loader_unlock ();
5070         locked = FALSE;
5071
5072         setup_interface_offsets (klass, first_iface_slot, TRUE);
5073
5074         if (mono_security_core_clr_enabled ())
5075                 mono_security_core_clr_check_inheritance (klass);
5076
5077         if (mono_class_is_ginst (klass) && !mono_verifier_class_is_valid_generic_instantiation (klass))
5078                 mono_class_set_type_load_failure (klass, "Invalid generic instantiation");
5079
5080         goto leave;
5081
5082  leave:
5083         init_list = g_slist_remove (init_list, klass);
5084         mono_native_tls_set_value (init_pending_tls_id, init_list);
5085
5086         if (locked)
5087                 mono_loader_unlock ();
5088
5089         /* Leave this for last */
5090         mono_loader_lock ();
5091         klass->inited = 1;
5092         mono_loader_unlock ();
5093
5094         return !mono_class_has_failure (klass);
5095 }
5096
5097 /*
5098  * mono_class_has_finalizer:
5099  *
5100  *   Return whenever KLASS has a finalizer, initializing klass->has_finalizer in the
5101  * process.
5102  */
5103 gboolean
5104 mono_class_has_finalizer (MonoClass *klass)
5105 {
5106         gboolean has_finalize = FALSE;
5107
5108         if (klass->has_finalize_inited)
5109                 return klass->has_finalize;
5110
5111         /* Interfaces and valuetypes are not supposed to have finalizers */
5112         if (!(MONO_CLASS_IS_INTERFACE (klass) || klass->valuetype)) {
5113                 MonoMethod *cmethod = NULL;
5114
5115                 if (klass->rank == 1 && klass->byval_arg.type == MONO_TYPE_SZARRAY) {
5116                 } else if (mono_class_is_ginst (klass)) {
5117                         MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
5118
5119                         has_finalize = mono_class_has_finalizer (gklass);
5120                 } else if (klass->parent && klass->parent->has_finalize) {
5121                         has_finalize = TRUE;
5122                 } else {
5123                         if (klass->parent) {
5124                                 /*
5125                                  * Can't search in metadata for a method named Finalize, because that
5126                                  * ignores overrides.
5127                                  */
5128                                 mono_class_setup_vtable (klass);
5129                                 if (mono_class_has_failure (klass))
5130                                         cmethod = NULL;
5131                                 else
5132                                         cmethod = klass->vtable [finalize_slot];
5133                         }
5134
5135                         if (cmethod) {
5136                                 g_assert (klass->vtable_size > finalize_slot);
5137
5138                                 if (klass->parent) {
5139                                         if (cmethod->is_inflated)
5140                                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
5141                                         if (cmethod != default_finalize)
5142                                                 has_finalize = TRUE;
5143                                 }
5144                         }
5145                 }
5146         }
5147
5148         mono_image_lock (klass->image);
5149
5150         if (!klass->has_finalize_inited) {
5151                 klass->has_finalize = has_finalize ? 1 : 0;
5152
5153                 mono_memory_barrier ();
5154                 klass->has_finalize_inited = TRUE;
5155         }
5156
5157         mono_image_unlock (klass->image);
5158
5159         return klass->has_finalize;
5160 }
5161
5162 gboolean
5163 mono_is_corlib_image (MonoImage *image)
5164 {
5165         return image == mono_defaults.corlib;
5166 }
5167
5168 /*
5169  * LOCKING: this assumes the loader lock is held
5170  */
5171 void
5172 mono_class_setup_mono_type (MonoClass *klass)
5173 {
5174         const char *name = klass->name;
5175         const char *nspace = klass->name_space;
5176         gboolean is_corlib = mono_is_corlib_image (klass->image);
5177
5178         klass->this_arg.byref = 1;
5179         klass->this_arg.data.klass = klass;
5180         klass->this_arg.type = MONO_TYPE_CLASS;
5181         klass->byval_arg.data.klass = klass;
5182         klass->byval_arg.type = MONO_TYPE_CLASS;
5183
5184         if (is_corlib && !strcmp (nspace, "System")) {
5185                 if (!strcmp (name, "ValueType")) {
5186                         /*
5187                          * do not set the valuetype bit for System.ValueType.
5188                          * klass->valuetype = 1;
5189                          */
5190                         klass->blittable = TRUE;
5191                 } else if (!strcmp (name, "Enum")) {
5192                         /*
5193                          * do not set the valuetype bit for System.Enum.
5194                          * klass->valuetype = 1;
5195                          */
5196                         klass->valuetype = 0;
5197                         klass->enumtype = 0;
5198                 } else if (!strcmp (name, "Object")) {
5199                         klass->byval_arg.type = MONO_TYPE_OBJECT;
5200                         klass->this_arg.type = MONO_TYPE_OBJECT;
5201                 } else if (!strcmp (name, "String")) {
5202                         klass->byval_arg.type = MONO_TYPE_STRING;
5203                         klass->this_arg.type = MONO_TYPE_STRING;
5204                 } else if (!strcmp (name, "TypedReference")) {
5205                         klass->byval_arg.type = MONO_TYPE_TYPEDBYREF;
5206                         klass->this_arg.type = MONO_TYPE_TYPEDBYREF;
5207                 }
5208         }
5209
5210         if (klass->valuetype) {
5211                 int t = MONO_TYPE_VALUETYPE;
5212
5213                 if (is_corlib && !strcmp (nspace, "System")) {
5214                         switch (*name) {
5215                         case 'B':
5216                                 if (!strcmp (name, "Boolean")) {
5217                                         t = MONO_TYPE_BOOLEAN;
5218                                 } else if (!strcmp(name, "Byte")) {
5219                                         t = MONO_TYPE_U1;
5220                                         klass->blittable = TRUE;                                                
5221                                 }
5222                                 break;
5223                         case 'C':
5224                                 if (!strcmp (name, "Char")) {
5225                                         t = MONO_TYPE_CHAR;
5226                                 }
5227                                 break;
5228                         case 'D':
5229                                 if (!strcmp (name, "Double")) {
5230                                         t = MONO_TYPE_R8;
5231                                         klass->blittable = TRUE;                                                
5232                                 }
5233                                 break;
5234                         case 'I':
5235                                 if (!strcmp (name, "Int32")) {
5236                                         t = MONO_TYPE_I4;
5237                                         klass->blittable = TRUE;
5238                                 } else if (!strcmp(name, "Int16")) {
5239                                         t = MONO_TYPE_I2;
5240                                         klass->blittable = TRUE;
5241                                 } else if (!strcmp(name, "Int64")) {
5242                                         t = MONO_TYPE_I8;
5243                                         klass->blittable = TRUE;
5244                                 } else if (!strcmp(name, "IntPtr")) {
5245                                         t = MONO_TYPE_I;
5246                                         klass->blittable = TRUE;
5247                                 }
5248                                 break;
5249                         case 'S':
5250                                 if (!strcmp (name, "Single")) {
5251                                         t = MONO_TYPE_R4;
5252                                         klass->blittable = TRUE;                                                
5253                                 } else if (!strcmp(name, "SByte")) {
5254                                         t = MONO_TYPE_I1;
5255                                         klass->blittable = TRUE;
5256                                 }
5257                                 break;
5258                         case 'U':
5259                                 if (!strcmp (name, "UInt32")) {
5260                                         t = MONO_TYPE_U4;
5261                                         klass->blittable = TRUE;
5262                                 } else if (!strcmp(name, "UInt16")) {
5263                                         t = MONO_TYPE_U2;
5264                                         klass->blittable = TRUE;
5265                                 } else if (!strcmp(name, "UInt64")) {
5266                                         t = MONO_TYPE_U8;
5267                                         klass->blittable = TRUE;
5268                                 } else if (!strcmp(name, "UIntPtr")) {
5269                                         t = MONO_TYPE_U;
5270                                         klass->blittable = TRUE;
5271                                 }
5272                                 break;
5273                         case 'T':
5274                                 if (!strcmp (name, "TypedReference")) {
5275                                         t = MONO_TYPE_TYPEDBYREF;
5276                                         klass->blittable = TRUE;
5277                                 }
5278                                 break;
5279                         case 'V':
5280                                 if (!strcmp (name, "Void")) {
5281                                         t = MONO_TYPE_VOID;
5282                                 }
5283                                 break;
5284                         default:
5285                                 break;
5286                         }
5287                 }
5288                 klass->byval_arg.type = (MonoTypeEnum)t;
5289                 klass->this_arg.type = (MonoTypeEnum)t;
5290         }
5291
5292         if (MONO_CLASS_IS_INTERFACE (klass)) {
5293                 klass->interface_id = mono_get_unique_iid (klass);
5294
5295                 if (is_corlib && !strcmp (nspace, "System.Collections.Generic")) {
5296                         //FIXME IEnumerator needs to be special because GetEnumerator uses magic under the hood
5297                     /* FIXME: System.Array/InternalEnumerator don't need all this interface fabrication machinery.
5298                     * MS returns diferrent types based on which instance is called. For example:
5299                     *   object obj = new byte[10][];
5300                     *   Type a = ((IEnumerable<byte[]>)obj).GetEnumerator ().GetType ();
5301                     *   Type b = ((IEnumerable<IList<byte>>)obj).GetEnumerator ().GetType ();
5302                     *   a != b ==> true
5303                         */
5304                         if (!strcmp (name, "IList`1") || !strcmp (name, "ICollection`1") || !strcmp (name, "IEnumerable`1") || !strcmp (name, "IEnumerator`1"))
5305                                 klass->is_array_special_interface = 1;
5306                 }
5307         }
5308 }
5309
5310 #ifndef DISABLE_COM
5311 /*
5312  * COM initialization is delayed until needed.
5313  * However when a [ComImport] attribute is present on a type it will trigger
5314  * the initialization. This is not a problem unless the BCL being executed 
5315  * lacks the types that COM depends on (e.g. Variant on Silverlight).
5316  */
5317 static void
5318 init_com_from_comimport (MonoClass *klass)
5319 {
5320         /* we don't always allow COM initialization under the CoreCLR (e.g. Moonlight does not require it) */
5321         if (mono_security_core_clr_enabled ()) {
5322                 /* but some other CoreCLR user could requires it for their platform (i.e. trusted) code */
5323                 if (!mono_security_core_clr_determine_platform_image (klass->image)) {
5324                         /* but it can not be made available for application (i.e. user code) since all COM calls
5325                          * are considered native calls. In this case we fail with a TypeLoadException (just like
5326                          * Silverlight 2 does */
5327                         mono_class_set_type_load_failure (klass, "");
5328                         return;
5329                 }
5330         }
5331
5332         /* FIXME : we should add an extra checks to ensure COM can be initialized properly before continuing */
5333 }
5334 #endif /*DISABLE_COM*/
5335
5336 /*
5337  * LOCKING: this assumes the loader lock is held
5338  */
5339 void
5340 mono_class_setup_parent (MonoClass *klass, MonoClass *parent)
5341 {
5342         gboolean system_namespace;
5343         gboolean is_corlib = mono_is_corlib_image (klass->image);
5344
5345         system_namespace = !strcmp (klass->name_space, "System") && is_corlib;
5346
5347         /* if root of the hierarchy */
5348         if (system_namespace && !strcmp (klass->name, "Object")) {
5349                 klass->parent = NULL;
5350                 klass->instance_size = sizeof (MonoObject);
5351                 return;
5352         }
5353         if (!strcmp (klass->name, "<Module>")) {
5354                 klass->parent = NULL;
5355                 klass->instance_size = 0;
5356                 return;
5357         }
5358
5359         if (!MONO_CLASS_IS_INTERFACE (klass)) {
5360                 /* Imported COM Objects always derive from __ComObject. */
5361 #ifndef DISABLE_COM
5362                 if (MONO_CLASS_IS_IMPORT (klass)) {
5363                         init_com_from_comimport (klass);
5364                         if (parent == mono_defaults.object_class)
5365                                 parent = mono_class_get_com_object_class ();
5366                 }
5367 #endif
5368                 if (!parent) {
5369                         /* set the parent to something useful and safe, but mark the type as broken */
5370                         parent = mono_defaults.object_class;
5371                         mono_class_set_type_load_failure (klass, "");
5372                         g_assert (parent);
5373                 }
5374
5375                 klass->parent = parent;
5376
5377                 if (mono_class_is_ginst (parent) && !parent->name) {
5378                         /*
5379                          * If the parent is a generic instance, we may get
5380                          * called before it is fully initialized, especially
5381                          * before it has its name.
5382                          */
5383                         return;
5384                 }
5385
5386 #ifndef DISABLE_REMOTING
5387                 klass->marshalbyref = parent->marshalbyref;
5388                 klass->contextbound  = parent->contextbound;
5389 #endif
5390
5391                 klass->delegate  = parent->delegate;
5392
5393                 if (MONO_CLASS_IS_IMPORT (klass) || mono_class_is_com_object (parent))
5394                         mono_class_set_is_com_object (klass);
5395                 
5396                 if (system_namespace) {
5397 #ifndef DISABLE_REMOTING
5398                         if (klass->name [0] == 'M' && !strcmp (klass->name, "MarshalByRefObject"))
5399                                 klass->marshalbyref = 1;
5400
5401                         if (klass->name [0] == 'C' && !strcmp (klass->name, "ContextBoundObject")) 
5402                                 klass->contextbound  = 1;
5403 #endif
5404                         if (klass->name [0] == 'D' && !strcmp (klass->name, "Delegate")) 
5405                                 klass->delegate  = 1;
5406                 }
5407
5408                 if (klass->parent->enumtype || (mono_is_corlib_image (klass->parent->image) && (strcmp (klass->parent->name, "ValueType") == 0) && 
5409                                                 (strcmp (klass->parent->name_space, "System") == 0)))
5410                         klass->valuetype = 1;
5411                 if (mono_is_corlib_image (klass->parent->image) && ((strcmp (klass->parent->name, "Enum") == 0) && (strcmp (klass->parent->name_space, "System") == 0))) {
5412                         klass->valuetype = klass->enumtype = 1;
5413                 }
5414                 /*klass->enumtype = klass->parent->enumtype; */
5415         } else {
5416                 /* initialize com types if COM interfaces are present */
5417 #ifndef DISABLE_COM
5418                 if (MONO_CLASS_IS_IMPORT (klass))
5419                         init_com_from_comimport (klass);
5420 #endif
5421                 klass->parent = NULL;
5422         }
5423
5424 }
5425
5426 /*
5427  * mono_class_setup_supertypes:
5428  * @class: a class
5429  *
5430  * Build the data structure needed to make fast type checks work.
5431  * This currently sets two fields in @class:
5432  *  - idepth: distance between @class and System.Object in the type
5433  *    hierarchy + 1
5434  *  - supertypes: array of classes: each element has a class in the hierarchy
5435  *    starting from @class up to System.Object
5436  * 
5437  * LOCKING: Acquires the loader lock.
5438  */
5439 void
5440 mono_class_setup_supertypes (MonoClass *klass)
5441 {
5442         int ms, idepth;
5443         MonoClass **supertypes;
5444
5445         mono_atomic_load_acquire (supertypes, MonoClass **, &klass->supertypes);
5446         if (supertypes)
5447                 return;
5448
5449         if (klass->parent && !klass->parent->supertypes)
5450                 mono_class_setup_supertypes (klass->parent);
5451         if (klass->parent)
5452                 idepth = klass->parent->idepth + 1;
5453         else
5454                 idepth = 1;
5455
5456         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, idepth);
5457         supertypes = (MonoClass **)mono_class_alloc0 (klass, sizeof (MonoClass *) * ms);
5458
5459         if (klass->parent) {
5460                 CHECKED_METADATA_WRITE_PTR ( supertypes [idepth - 1] , klass );
5461
5462                 int supertype_idx;
5463                 for (supertype_idx = 0; supertype_idx < klass->parent->idepth; supertype_idx++)
5464                         CHECKED_METADATA_WRITE_PTR ( supertypes [supertype_idx] , klass->parent->supertypes [supertype_idx] );
5465         } else {
5466                 CHECKED_METADATA_WRITE_PTR ( supertypes [0] , klass );
5467         }
5468
5469         mono_memory_barrier ();
5470
5471         mono_loader_lock ();
5472         klass->idepth = idepth;
5473         /* Needed so idepth is visible before supertypes is set */
5474         mono_memory_barrier ();
5475         klass->supertypes = supertypes;
5476         mono_loader_unlock ();
5477 }
5478
5479 static gboolean
5480 fix_gclass_incomplete_instantiation (MonoClass *gclass, void *user_data)
5481 {
5482         MonoClass *gtd = (MonoClass*)user_data;
5483         /* Only try to fix generic instances of @gtd */
5484         if (mono_class_get_generic_class (gclass)->container_class != gtd)
5485                 return FALSE;
5486
5487         /* Check if the generic instance has no parent. */
5488         if (gtd->parent && !gclass->parent)
5489                 mono_generic_class_setup_parent (gclass, gtd);
5490
5491         return TRUE;
5492 }
5493
5494 static void
5495 mono_class_set_failure_and_error (MonoClass *klass, MonoError *error, const char *msg)
5496 {
5497         mono_class_set_type_load_failure (klass, "%s", msg);
5498         mono_error_set_type_load_class (error, klass, "%s", msg);
5499 }
5500
5501 /**
5502  * mono_class_create_from_typedef:
5503  * @image: image where the token is valid
5504  * @type_token:  typedef token
5505  * @error:  used to return any error found while creating the type
5506  *
5507  * Create the MonoClass* representing the specified type token.
5508  * @type_token must be a TypeDef token.
5509  *
5510  * FIXME: don't return NULL on failure, just the the caller figure it out.
5511  */
5512 static MonoClass *
5513 mono_class_create_from_typedef (MonoImage *image, guint32 type_token, MonoError *error)
5514 {
5515         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
5516         MonoClass *klass, *parent = NULL;
5517         guint32 cols [MONO_TYPEDEF_SIZE];
5518         guint32 cols_next [MONO_TYPEDEF_SIZE];
5519         guint tidx = mono_metadata_token_index (type_token);
5520         MonoGenericContext *context = NULL;
5521         const char *name, *nspace;
5522         guint icount = 0; 
5523         MonoClass **interfaces;
5524         guint32 field_last, method_last;
5525         guint32 nesting_tokeen;
5526
5527         mono_error_init (error);
5528
5529         if (mono_metadata_token_table (type_token) != MONO_TABLE_TYPEDEF || tidx > tt->rows) {
5530                 mono_error_set_bad_image (error, image, "Invalid typedef token %x", type_token);
5531                 return NULL;
5532         }
5533
5534         mono_loader_lock ();
5535
5536         if ((klass = (MonoClass *)mono_internal_hash_table_lookup (&image->class_cache, GUINT_TO_POINTER (type_token)))) {
5537                 mono_loader_unlock ();
5538                 return klass;
5539         }
5540
5541         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
5542         
5543         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
5544         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
5545
5546         if (mono_metadata_has_generic_params (image, type_token)) {
5547                 klass = mono_image_alloc0 (image, sizeof (MonoClassGtd));
5548                 klass->class_kind = MONO_CLASS_GTD;
5549                 classes_size += sizeof (MonoClassGtd);
5550                 ++class_gtd_count;
5551         } else {
5552                 klass = mono_image_alloc0 (image, sizeof (MonoClassDef));
5553                 klass->class_kind = MONO_CLASS_DEF;
5554                 classes_size += sizeof (MonoClassDef);
5555                 ++class_def_count;
5556         }
5557
5558         klass->name = name;
5559         klass->name_space = nspace;
5560
5561         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5562
5563         klass->image = image;
5564         klass->type_token = type_token;
5565         mono_class_set_flags (klass, cols [MONO_TYPEDEF_FLAGS]);
5566
5567         mono_internal_hash_table_insert (&image->class_cache, GUINT_TO_POINTER (type_token), klass);
5568
5569         /*
5570          * Check whether we're a generic type definition.
5571          */
5572         if (mono_class_is_gtd (klass)) {
5573                 MonoGenericContainer *generic_container = mono_metadata_load_generic_params (image, klass->type_token, NULL);
5574                 generic_container->owner.klass = klass;
5575                 generic_container->is_anonymous = FALSE; // Owner class is now known, container is no longer anonymous
5576                 context = &generic_container->context;
5577                 mono_class_set_generic_container (klass, generic_container);
5578                 enable_gclass_recording ();
5579         }
5580
5581         if (cols [MONO_TYPEDEF_EXTENDS]) {
5582                 MonoClass *tmp;
5583                 guint32 parent_token = mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]);
5584
5585                 if (mono_metadata_token_table (parent_token) == MONO_TABLE_TYPESPEC) {
5586                         /*WARNING: this must satisfy mono_metadata_type_hash*/
5587                         klass->this_arg.byref = 1;
5588                         klass->this_arg.data.klass = klass;
5589                         klass->this_arg.type = MONO_TYPE_CLASS;
5590                         klass->byval_arg.data.klass = klass;
5591                         klass->byval_arg.type = MONO_TYPE_CLASS;
5592                 }
5593                 parent = mono_class_get_checked (image, parent_token, error);
5594                 if (parent && context) /* Always inflate */
5595                         parent = mono_class_inflate_generic_class_checked (parent, context, error);
5596
5597                 if (parent == NULL) {
5598                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5599                         goto parent_failure;
5600                 }
5601
5602                 for (tmp = parent; tmp; tmp = tmp->parent) {
5603                         if (tmp == klass) {
5604                                 mono_class_set_failure_and_error (klass, error, "Cycle found while resolving parent");
5605                                 goto parent_failure;
5606                         }
5607                         if (mono_class_is_gtd (klass) && mono_class_is_ginst (tmp) && mono_class_get_generic_class (tmp)->container_class == klass) {
5608                                 mono_class_set_failure_and_error (klass, error, "Parent extends generic instance of this type");
5609                                 goto parent_failure;
5610                         }
5611                 }
5612         }
5613
5614         mono_class_setup_parent (klass, parent);
5615
5616         /* uses ->valuetype, which is initialized by mono_class_setup_parent above */
5617         mono_class_setup_mono_type (klass);
5618
5619         if (mono_class_is_gtd (klass))
5620                 disable_gclass_recording (fix_gclass_incomplete_instantiation, klass);
5621
5622         /* 
5623          * This might access klass->byval_arg for recursion generated by generic constraints,
5624          * so it has to come after setup_mono_type ().
5625          */
5626         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token))) {
5627                 klass->nested_in = mono_class_create_from_typedef (image, nesting_tokeen, error);
5628                 if (!mono_error_ok (error)) {
5629                         /*FIXME implement a mono_class_set_failure_from_mono_error */
5630                         mono_class_set_type_load_failure (klass, "%s",  mono_error_get_message (error));
5631                         mono_loader_unlock ();
5632                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5633                         return NULL;
5634                 }
5635         }
5636
5637         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
5638                 klass->unicode = 1;
5639
5640 #ifdef HOST_WIN32
5641         if ((mono_class_get_flags (klass) & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
5642                 klass->unicode = 1;
5643 #endif
5644
5645         klass->cast_class = klass->element_class = klass;
5646         if (mono_is_corlib_image (klass->image)) {
5647                 switch (klass->byval_arg.type) {
5648                         case MONO_TYPE_I1:
5649                                 if (mono_defaults.byte_class)
5650                                         klass->cast_class = mono_defaults.byte_class;
5651                                 break;
5652                         case MONO_TYPE_U1:
5653                                 if (mono_defaults.sbyte_class)
5654                                         mono_defaults.sbyte_class = klass;
5655                                 break;
5656                         case MONO_TYPE_I2:
5657                                 if (mono_defaults.uint16_class)
5658                                         mono_defaults.uint16_class = klass;
5659                                 break;
5660                         case MONO_TYPE_U2:
5661                                 if (mono_defaults.int16_class)
5662                                         klass->cast_class = mono_defaults.int16_class;
5663                                 break;
5664                         case MONO_TYPE_I4:
5665                                 if (mono_defaults.uint32_class)
5666                                         mono_defaults.uint32_class = klass;
5667                                 break;
5668                         case MONO_TYPE_U4:
5669                                 if (mono_defaults.int32_class)
5670                                         klass->cast_class = mono_defaults.int32_class;
5671                                 break;
5672                         case MONO_TYPE_I8:
5673                                 if (mono_defaults.uint64_class)
5674                                         mono_defaults.uint64_class = klass;
5675                                 break;
5676                         case MONO_TYPE_U8:
5677                                 if (mono_defaults.int64_class)
5678                                         klass->cast_class = mono_defaults.int64_class;
5679                                 break;
5680                 }
5681         }
5682
5683         if (!klass->enumtype) {
5684                 if (!mono_metadata_interfaces_from_typedef_full (
5685                             image, type_token, &interfaces, &icount, FALSE, context, error)){
5686
5687                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5688                         mono_loader_unlock ();
5689                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5690                         return NULL;
5691                 }
5692
5693                 /* This is required now that it is possible for more than 2^16 interfaces to exist. */
5694                 g_assert(icount <= 65535);
5695
5696                 klass->interfaces = interfaces;
5697                 klass->interface_count = icount;
5698                 klass->interfaces_inited = 1;
5699         }
5700
5701         /*g_print ("Load class %s\n", name);*/
5702
5703         /*
5704          * Compute the field and method lists
5705          */
5706         int first_field_idx = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
5707         mono_class_set_first_field_idx (klass, first_field_idx);
5708         int first_method_idx = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
5709         mono_class_set_first_method_idx (klass, first_method_idx);
5710
5711         if (tt->rows > tidx){           
5712                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
5713                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
5714                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
5715         } else {
5716                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
5717                 method_last = image->tables [MONO_TABLE_METHOD].rows;
5718         }
5719
5720         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
5721             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
5722                 mono_class_set_field_count (klass, field_last - first_field_idx);
5723         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
5724                 mono_class_set_method_count (klass, method_last - first_method_idx);
5725
5726         /* reserve space to store vector pointer in arrays */
5727         if (mono_is_corlib_image (image) && !strcmp (nspace, "System") && !strcmp (name, "Array")) {
5728                 klass->instance_size += 2 * sizeof (gpointer);
5729                 g_assert (mono_class_get_field_count (klass) == 0);
5730         }
5731
5732         if (klass->enumtype) {
5733                 MonoType *enum_basetype = mono_class_find_enum_basetype (klass, error);
5734                 if (!enum_basetype) {
5735                         /*set it to a default value as the whole runtime can't handle this to be null*/
5736                         klass->cast_class = klass->element_class = mono_defaults.int32_class;
5737                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
5738                         mono_loader_unlock ();
5739                         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5740                         return NULL;
5741                 }
5742                 klass->cast_class = klass->element_class = mono_class_from_mono_type (enum_basetype);
5743         }
5744
5745         /*
5746          * If we're a generic type definition, load the constraints.
5747          * We must do this after the class has been constructed to make certain recursive scenarios
5748          * work.
5749          */
5750         if (mono_class_is_gtd (klass) && !mono_metadata_load_generic_param_constraints_checked (image, type_token, mono_class_get_generic_container (klass), error)) {
5751                 mono_class_set_type_load_failure (klass, "Could not load generic parameter constrains due to %s", mono_error_get_message (error));
5752                 mono_loader_unlock ();
5753                 mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5754                 return NULL;
5755         }
5756
5757         if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "Mono.Simd") && !strcmp (nspace, "Mono.Simd")) {
5758                 if (!strncmp (name, "Vector", 6))
5759                         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");
5760         } else if (klass->image->assembly_name && !strcmp (klass->image->assembly_name, "System.Numerics") && !strcmp (nspace, "System.Numerics")) {
5761                 if (!strcmp (name, "Vector2") || !strcmp (name, "Vector3") || !strcmp (name, "Vector4"))
5762                         klass->simd_type = 1;
5763         }
5764
5765         mono_loader_unlock ();
5766
5767         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5768
5769         return klass;
5770
5771 parent_failure:
5772         mono_class_setup_mono_type (klass);
5773         mono_loader_unlock ();
5774         mono_profiler_class_loaded (klass, MONO_PROFILE_FAILED);
5775         return NULL;
5776 }
5777
5778 /** Is klass a Nullable<T> ginst? */
5779 gboolean
5780 mono_class_is_nullable (MonoClass *klass)
5781 {
5782         MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
5783         return gklass && gklass->container_class == mono_defaults.generic_nullable_class;
5784 }
5785
5786
5787 /** if klass is T? return T */
5788 MonoClass*
5789 mono_class_get_nullable_param (MonoClass *klass)
5790 {
5791        g_assert (mono_class_is_nullable (klass));
5792        return mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
5793 }
5794
5795 static void
5796 mono_generic_class_setup_parent (MonoClass *klass, MonoClass *gtd)
5797 {
5798         if (gtd->parent) {
5799                 MonoError error;
5800                 MonoGenericClass *gclass = mono_class_get_generic_class (klass);
5801
5802                 klass->parent = mono_class_inflate_generic_class_checked (gtd->parent, mono_generic_class_get_context (gclass), &error);
5803                 if (!mono_error_ok (&error)) {
5804                         /*Set parent to something safe as the runtime doesn't handle well this kind of failure.*/
5805                         klass->parent = mono_defaults.object_class;
5806                         mono_class_set_type_load_failure (klass, "Parent is a generic type instantiation that failed due to: %s", mono_error_get_message (&error));
5807                         mono_error_cleanup (&error);
5808                 }
5809         }
5810         if (klass->parent)
5811                 mono_class_setup_parent (klass, klass->parent);
5812
5813         if (klass->enumtype) {
5814                 klass->cast_class = gtd->cast_class;
5815                 klass->element_class = gtd->element_class;
5816         }
5817 }
5818
5819 gboolean
5820 mono_type_is_primitive (MonoType *type)
5821 {
5822         return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
5823                         type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
5824 }
5825
5826 /*
5827  * Create the `MonoClass' for an instantiation of a generic type.
5828  * We only do this if we actually need it.
5829  */
5830 MonoClass*
5831 mono_generic_class_get_class (MonoGenericClass *gclass)
5832 {
5833         MonoClass *klass, *gklass;
5834
5835         if (gclass->cached_class)
5836                 return gclass->cached_class;
5837
5838         klass = (MonoClass *)mono_image_set_alloc0 (gclass->owner, sizeof (MonoClassGenericInst));
5839
5840         gklass = gclass->container_class;
5841
5842         if (gklass->nested_in) {
5843                 /* The nested_in type should not be inflated since it's possible to produce a nested type with less generic arguments*/
5844                 klass->nested_in = gklass->nested_in;
5845         }
5846
5847         klass->name = gklass->name;
5848         klass->name_space = gklass->name_space;
5849         
5850         klass->image = gklass->image;
5851         klass->type_token = gklass->type_token;
5852
5853         klass->class_kind = MONO_CLASS_GINST;
5854         //FIXME add setter
5855         ((MonoClassGenericInst*)klass)->generic_class = gclass;
5856
5857         klass->byval_arg.type = MONO_TYPE_GENERICINST;
5858         klass->this_arg.type = klass->byval_arg.type;
5859         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = gclass;
5860         klass->this_arg.byref = TRUE;
5861         klass->enumtype = gklass->enumtype;
5862         klass->valuetype = gklass->valuetype;
5863
5864
5865         if (gklass->image->assembly_name && !strcmp (gklass->image->assembly_name, "System.Numerics.Vectors") && !strcmp (gklass->name_space, "System.Numerics") && !strcmp (gklass->name, "Vector`1")) {
5866                 g_assert (gclass->context.class_inst);
5867                 g_assert (gclass->context.class_inst->type_argc > 0);
5868                 if (mono_type_is_primitive (gclass->context.class_inst->type_argv [0]))
5869                         klass->simd_type = 1;
5870         }
5871         klass->is_array_special_interface = gklass->is_array_special_interface;
5872
5873         klass->cast_class = klass->element_class = klass;
5874
5875         if (gclass->is_dynamic) {
5876                 /*
5877                  * 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.
5878                  * This is to avoid work that would probably give wrong results as fields change as we build the TypeBuilder.
5879                  * See remove_instantiations_of_and_ensure_contents in reflection.c and its usage in reflection.c to understand the fixup stage of SRE banking.
5880                 */
5881                 if (!gklass->wastypebuilder)
5882                         klass->inited = 1;
5883
5884                 if (klass->enumtype) {
5885                         /*
5886                          * For enums, gklass->fields might not been set, but instance_size etc. is 
5887                          * already set in mono_reflection_create_internal_class (). For non-enums,
5888                          * these will be computed normally in mono_class_layout_fields ().
5889                          */
5890                         klass->instance_size = gklass->instance_size;
5891                         klass->sizes.class_size = gklass->sizes.class_size;
5892                         klass->size_inited = 1;
5893                 }
5894         }
5895
5896         mono_loader_lock ();
5897
5898         if (gclass->cached_class) {
5899                 mono_loader_unlock ();
5900                 return gclass->cached_class;
5901         }
5902
5903         if (record_gclass_instantiation > 0)
5904                 gclass_recorded_list = g_slist_append (gclass_recorded_list, klass);
5905
5906         if (mono_class_is_nullable (klass))
5907                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
5908
5909         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
5910
5911         mono_generic_class_setup_parent (klass, gklass);
5912
5913         if (gclass->is_dynamic)
5914                 mono_class_setup_supertypes (klass);
5915
5916         mono_memory_barrier ();
5917         gclass->cached_class = klass;
5918
5919         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
5920
5921         ++class_ginst_count;
5922         inflated_classes_size += sizeof (MonoClassGenericInst);
5923         
5924         mono_loader_unlock ();
5925
5926         return klass;
5927 }
5928
5929 static MonoImage *
5930 get_image_for_container (MonoGenericContainer *container)
5931 {
5932         MonoImage *result;
5933         if (container->is_anonymous) {
5934                 result = container->owner.image;
5935         } else {
5936                 MonoClass *klass;
5937                 if (container->is_method) {
5938                         MonoMethod *method = container->owner.method;
5939                         g_assert_checked (method);
5940                         klass = method->klass;
5941                 } else {
5942                         klass = container->owner.klass;
5943                 }
5944                 g_assert_checked (klass);
5945                 result = klass->image;
5946         }
5947         g_assert (result);
5948         return result;
5949 }
5950
5951 MonoImage *
5952 get_image_for_generic_param (MonoGenericParam *param)
5953 {
5954         MonoGenericContainer *container = mono_generic_param_owner (param);
5955         g_assert_checked (container);
5956         return get_image_for_container (container);
5957 }
5958
5959 // Make a string in the designated image consisting of a single integer.
5960 #define INT_STRING_SIZE 16
5961 char *
5962 make_generic_name_string (MonoImage *image, int num)
5963 {
5964         char *name = (char *)mono_image_alloc0 (image, INT_STRING_SIZE);
5965         g_snprintf (name, INT_STRING_SIZE, "%d", num);
5966         return name;
5967 }
5968
5969 // This is called by mono_class_from_generic_parameter_internal when a new class must be created.
5970 // pinfo is derived from param by the caller for us.
5971 static MonoClass*
5972 make_generic_param_class (MonoGenericParam *param, MonoGenericParamInfo *pinfo)
5973 {
5974         MonoClass *klass, **ptr;
5975         int count, pos, i;
5976         MonoGenericContainer *container = mono_generic_param_owner (param);
5977         g_assert_checked (container);
5978
5979         MonoImage *image = get_image_for_container (container);
5980         gboolean is_mvar = container->is_method;
5981         gboolean is_anonymous = container->is_anonymous;
5982
5983         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassGenericParam));
5984         klass->class_kind = MONO_CLASS_GPARAM;
5985         classes_size += sizeof (MonoClassGenericParam);
5986         ++class_gparam_count;
5987
5988         if (pinfo) {
5989                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name , pinfo->name );
5990         } else {
5991                 int n = mono_generic_param_num (param);
5992                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->name , make_generic_name_string (image, n) );
5993         }
5994
5995         if (is_anonymous) {
5996                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space ,  "" );
5997         } else if (is_mvar) {
5998                 MonoMethod *omethod = container->owner.method;
5999                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , (omethod && omethod->klass) ? omethod->klass->name_space : "" );
6000         } else {
6001                 MonoClass *oklass = container->owner.klass;
6002                 CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->name_space , oklass ? oklass->name_space : "" );
6003         }
6004
6005         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6006
6007         // Count non-NULL items in pinfo->constraints
6008         count = 0;
6009         if (pinfo)
6010                 for (ptr = pinfo->constraints; ptr && *ptr; ptr++, count++)
6011                         ;
6012
6013         pos = 0;
6014         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (pinfo->constraints [0])) {
6015                 CHECKED_METADATA_WRITE_PTR ( klass->parent , pinfo->constraints [0] );
6016                 pos++;
6017         } else if (pinfo && pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) {
6018                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_class_load_from_name (mono_defaults.corlib, "System", "ValueType") );
6019         } else {
6020                 CHECKED_METADATA_WRITE_PTR ( klass->parent , mono_defaults.object_class );
6021         }
6022
6023         if (count - pos > 0) {
6024                 klass->interface_count = count - pos;
6025                 CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->interfaces , (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass *) * (count - pos)) );
6026                 klass->interfaces_inited = TRUE;
6027                 for (i = pos; i < count; i++)
6028                         CHECKED_METADATA_WRITE_PTR ( klass->interfaces [i - pos] , pinfo->constraints [i] );
6029         }
6030
6031         CHECKED_METADATA_WRITE_PTR_EXEMPT ( klass->image , image );
6032
6033         klass->inited = TRUE;
6034         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->cast_class ,    klass );
6035         CHECKED_METADATA_WRITE_PTR_LOCAL ( klass->element_class , klass );
6036
6037         klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
6038         klass->this_arg.type = klass->byval_arg.type;
6039         CHECKED_METADATA_WRITE_PTR ( klass->this_arg.data.generic_param ,  param );
6040         CHECKED_METADATA_WRITE_PTR ( klass->byval_arg.data.generic_param , param );
6041         klass->this_arg.byref = TRUE;
6042
6043         /* We don't use type_token for VAR since only classes can use it (not arrays, pointer, VARs, etc) */
6044         klass->sizes.generic_param_token = pinfo ? pinfo->token : 0;
6045
6046         /*Init these fields to sane values*/
6047         klass->min_align = 1;
6048         /*
6049          * This makes sure the the value size of this class is equal to the size of the types the gparam is
6050          * constrained to, the JIT depends on this.
6051          */
6052         klass->instance_size = sizeof (MonoObject) + mono_type_stack_size_internal (&klass->byval_arg, NULL, TRUE);
6053         mono_memory_barrier ();
6054         klass->size_inited = 1;
6055
6056         mono_class_setup_supertypes (klass);
6057
6058         if (count - pos > 0) {
6059                 mono_class_setup_vtable (klass->parent);
6060                 if (mono_class_has_failure (klass->parent))
6061                         mono_class_set_type_load_failure (klass, "Failed to setup parent interfaces");
6062                 else
6063                         setup_interface_offsets (klass, klass->parent->vtable_size, TRUE);
6064         }
6065
6066         return klass;
6067 }
6068
6069 #define FAST_CACHE_SIZE 16
6070
6071 /*
6072  * get_anon_gparam_class and set_anon_gparam_class are helpers for mono_class_from_generic_parameter_internal.
6073  * The latter will sometimes create MonoClasses for anonymous generic params. To prevent this being wasteful,
6074  * we cache the MonoClasses.
6075  * FIXME: It would be better to instead cache anonymous MonoGenericParams, and allow anonymous params to point directly to classes using the pklass field.
6076  * LOCKING: Takes the image lock depending on @take_lock.
6077  */
6078 static MonoClass *
6079 get_anon_gparam_class (MonoGenericParam *param, gboolean take_lock)
6080 {
6081         int n = mono_generic_param_num (param);
6082         MonoImage *image = get_image_for_generic_param (param);
6083         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6084         MonoClass *klass = NULL;
6085         GHashTable *ht;
6086
6087         g_assert (image);
6088
6089         // For params with a small num and no constraints, we use a "fast" cache which does simple num lookup in an array.
6090         // For high numbers or constraints we have to use pointer hashes.
6091         if (param->gshared_constraint) {
6092                 ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6093                 if (ht) {
6094                         if (take_lock)
6095                                 mono_image_lock (image);
6096                         klass = (MonoClass *)g_hash_table_lookup (ht, param);
6097                         if (take_lock)
6098                                 mono_image_unlock (image);
6099                 }
6100                 return klass;
6101         }
6102
6103         if (n < FAST_CACHE_SIZE) {
6104                 if (is_mvar)
6105                         return image->mvar_cache_fast ? image->mvar_cache_fast [n] : NULL;
6106                 else
6107                         return image->var_cache_fast ? image->var_cache_fast [n] : NULL;
6108         } else {
6109                 ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6110                 if (ht) {
6111                         if (take_lock)
6112                                 mono_image_lock (image);
6113                         klass = (MonoClass *)g_hash_table_lookup (ht, GINT_TO_POINTER (n));
6114                         if (take_lock)
6115                                 mono_image_unlock (image);
6116                 }
6117                 return klass;
6118         }
6119 }
6120
6121 /*
6122  * LOCKING: Image lock (param->image) must be held
6123  */
6124 static void
6125 set_anon_gparam_class (MonoGenericParam *param, MonoClass *klass)
6126 {
6127         int n = mono_generic_param_num (param);
6128         MonoImage *image = get_image_for_generic_param (param);
6129         gboolean is_mvar = mono_generic_param_owner (param)->is_method;
6130
6131         g_assert (image);
6132
6133         if (param->gshared_constraint) {
6134                 GHashTable *ht = is_mvar ? image->mvar_cache_constrained : image->var_cache_constrained;
6135                 if (!ht) {
6136                         ht = g_hash_table_new ((GHashFunc)mono_metadata_generic_param_hash, (GEqualFunc)mono_metadata_generic_param_equal);
6137                         mono_memory_barrier ();
6138                         if (is_mvar)
6139                                 image->mvar_cache_constrained = ht;
6140                         else
6141                                 image->var_cache_constrained = ht;
6142                 }
6143                 g_hash_table_insert (ht, param, klass);
6144         } else if (n < FAST_CACHE_SIZE) {
6145                 if (is_mvar) {
6146                         /* Requires locking to avoid droping an already published class */
6147                         if (!image->mvar_cache_fast)
6148                                 image->mvar_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6149                         image->mvar_cache_fast [n] = klass;
6150                 } else {
6151                         if (!image->var_cache_fast)
6152                                 image->var_cache_fast = (MonoClass **)mono_image_alloc0 (image, sizeof (MonoClass*) * FAST_CACHE_SIZE);
6153                         image->var_cache_fast [n] = klass;
6154                 }
6155         } else {
6156                 GHashTable *ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6157                 if (!ht) {
6158                         ht = is_mvar ? image->mvar_cache_slow : image->var_cache_slow;
6159                         if (!ht) {
6160                                 ht = g_hash_table_new (NULL, NULL);
6161                                 mono_memory_barrier ();
6162                                 if (is_mvar)
6163                                         image->mvar_cache_slow = ht;
6164                                 else
6165                                         image->var_cache_slow = ht;
6166                         }
6167                 }
6168                 g_hash_table_insert (ht, GINT_TO_POINTER (n), klass);
6169         }
6170 }
6171
6172 /*
6173  * LOCKING: Acquires the image lock (@image).
6174  */
6175 MonoClass *
6176 mono_class_from_generic_parameter_internal (MonoGenericParam *param)
6177 {
6178         MonoImage *image = get_image_for_generic_param (param);
6179         MonoGenericParamInfo *pinfo = mono_generic_param_info (param);
6180         MonoClass *klass, *klass2;
6181
6182         // If a klass already exists for this object and is cached, return it.
6183         if (pinfo) // Non-anonymous
6184                 klass = pinfo->pklass;
6185         else     // Anonymous
6186                 klass = get_anon_gparam_class (param, TRUE);
6187
6188         if (klass)
6189                 return klass;
6190
6191         // Create a new klass
6192         klass = make_generic_param_class (param, pinfo);
6193
6194         // Now we need to cache the klass we created.
6195         // But since we wait to grab the lock until after creating the klass, we need to check to make sure
6196         // another thread did not get in and cache a klass ahead of us. In that case, return their klass
6197         // and allow our newly-created klass object to just leak.
6198         mono_memory_barrier ();
6199
6200         mono_image_lock (image);
6201
6202     // Here "klass2" refers to the klass potentially created by the other thread.
6203         if (pinfo) // Repeat check from above
6204                 klass2 = pinfo->pklass;
6205         else
6206                 klass2 = get_anon_gparam_class (param, FALSE);
6207
6208         if (klass2) {
6209                 klass = klass2;
6210         } else {
6211                 // Cache here
6212                 if (pinfo)
6213                         pinfo->pklass = klass;
6214                 else
6215                         set_anon_gparam_class (param, klass);
6216         }
6217         mono_image_unlock (image);
6218
6219         /* FIXME: Should this go inside 'make_generic_param_klass'? */
6220         if (klass2)
6221                 mono_profiler_class_loaded (klass2, MONO_PROFILE_FAILED); // Alert profiler about botched class create
6222         else
6223                 mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6224
6225         return klass;
6226 }
6227
6228 /**
6229  * mono_class_from_generic_parameter:
6230  * @param: Parameter to find/construct a class for.
6231  * @arg2: Is ignored.
6232  * @arg3: Is ignored.
6233  */
6234 MonoClass *
6235 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *arg2 G_GNUC_UNUSED, gboolean arg3 G_GNUC_UNUSED)
6236 {
6237         return mono_class_from_generic_parameter_internal (param);
6238 }
6239
6240 MonoClass *
6241 mono_ptr_class_get (MonoType *type)
6242 {
6243         MonoClass *result;
6244         MonoClass *el_class;
6245         MonoImage *image;
6246         char *name;
6247
6248         el_class = mono_class_from_mono_type (type);
6249         image = el_class->image;
6250
6251         mono_image_lock (image);
6252         if (image->ptr_cache) {
6253                 if ((result = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6254                         mono_image_unlock (image);
6255                         return result;
6256                 }
6257         }
6258         mono_image_unlock (image);
6259         
6260         result = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassPointer));
6261
6262         classes_size += sizeof (MonoClassPointer);
6263         ++class_pointer_count;
6264
6265         result->parent = NULL; /* no parent for PTR types */
6266         result->name_space = el_class->name_space;
6267         name = g_strdup_printf ("%s*", el_class->name);
6268         result->name = mono_image_strdup (image, name);
6269         result->class_kind = MONO_CLASS_POINTER;
6270         g_free (name);
6271
6272         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6273
6274         result->image = el_class->image;
6275         result->inited = TRUE;
6276         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6277         result->cast_class = result->element_class = el_class;
6278         result->blittable = TRUE;
6279
6280         result->byval_arg.type = MONO_TYPE_PTR;
6281         result->this_arg.type = result->byval_arg.type;
6282         result->this_arg.data.type = result->byval_arg.data.type = &result->element_class->byval_arg;
6283         result->this_arg.byref = TRUE;
6284
6285         mono_class_setup_supertypes (result);
6286
6287         mono_image_lock (image);
6288         if (image->ptr_cache) {
6289                 MonoClass *result2;
6290                 if ((result2 = (MonoClass *)g_hash_table_lookup (image->ptr_cache, el_class))) {
6291                         mono_image_unlock (image);
6292                         mono_profiler_class_loaded (result, MONO_PROFILE_FAILED);
6293                         return result2;
6294                 }
6295         } else {
6296                 image->ptr_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6297         }
6298         g_hash_table_insert (image->ptr_cache, el_class, result);
6299         mono_image_unlock (image);
6300
6301         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6302
6303         return result;
6304 }
6305
6306 static MonoClass *
6307 mono_fnptr_class_get (MonoMethodSignature *sig)
6308 {
6309         MonoClass *result, *cached;
6310         static GHashTable *ptr_hash = NULL;
6311
6312         /* FIXME: These should be allocate from a mempool as well, but which one ? */
6313
6314         mono_loader_lock ();
6315         if (!ptr_hash)
6316                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
6317         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6318         mono_loader_unlock ();
6319         if (cached)
6320                 return cached;
6321
6322         result = g_new0 (MonoClass, 1);
6323
6324         result->parent = NULL; /* no parent for PTR types */
6325         result->name_space = "System";
6326         result->name = "MonoFNPtrFakeClass";
6327         result->class_kind = MONO_CLASS_POINTER;
6328
6329         result->image = mono_defaults.corlib; /* need to fix... */
6330         result->instance_size = sizeof (MonoObject) + sizeof (gpointer);
6331         result->cast_class = result->element_class = result;
6332         result->byval_arg.type = MONO_TYPE_FNPTR;
6333         result->this_arg.type = result->byval_arg.type;
6334         result->this_arg.data.method = result->byval_arg.data.method = sig;
6335         result->this_arg.byref = TRUE;
6336         result->blittable = TRUE;
6337         result->inited = TRUE;
6338
6339         mono_class_setup_supertypes (result);
6340
6341         mono_loader_lock ();
6342
6343         cached = (MonoClass *)g_hash_table_lookup (ptr_hash, sig);
6344         if (cached) {
6345                 g_free (result);
6346                 mono_loader_unlock ();
6347                 return cached;
6348         }
6349
6350         mono_profiler_class_event (result, MONO_PROFILE_START_LOAD);
6351
6352         classes_size += sizeof (MonoClassPointer);
6353         ++class_pointer_count;
6354
6355         g_hash_table_insert (ptr_hash, sig, result);
6356
6357         mono_loader_unlock ();
6358
6359         mono_profiler_class_loaded (result, MONO_PROFILE_OK);
6360
6361         return result;
6362 }
6363
6364 /**
6365  * mono_class_from_mono_type:
6366  * @type: describes the type to return
6367  *
6368  * This returns a MonoClass for the specified MonoType, the value is never NULL.
6369  */
6370 MonoClass *
6371 mono_class_from_mono_type (MonoType *type)
6372 {
6373         switch (type->type) {
6374         case MONO_TYPE_OBJECT:
6375                 return type->data.klass? type->data.klass: mono_defaults.object_class;
6376         case MONO_TYPE_VOID:
6377                 return type->data.klass? type->data.klass: mono_defaults.void_class;
6378         case MONO_TYPE_BOOLEAN:
6379                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
6380         case MONO_TYPE_CHAR:
6381                 return type->data.klass? type->data.klass: mono_defaults.char_class;
6382         case MONO_TYPE_I1:
6383                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
6384         case MONO_TYPE_U1:
6385                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
6386         case MONO_TYPE_I2:
6387                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
6388         case MONO_TYPE_U2:
6389                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
6390         case MONO_TYPE_I4:
6391                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
6392         case MONO_TYPE_U4:
6393                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
6394         case MONO_TYPE_I:
6395                 return type->data.klass? type->data.klass: mono_defaults.int_class;
6396         case MONO_TYPE_U:
6397                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
6398         case MONO_TYPE_I8:
6399                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
6400         case MONO_TYPE_U8:
6401                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
6402         case MONO_TYPE_R4:
6403                 return type->data.klass? type->data.klass: mono_defaults.single_class;
6404         case MONO_TYPE_R8:
6405                 return type->data.klass? type->data.klass: mono_defaults.double_class;
6406         case MONO_TYPE_STRING:
6407                 return type->data.klass? type->data.klass: mono_defaults.string_class;
6408         case MONO_TYPE_TYPEDBYREF:
6409                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
6410         case MONO_TYPE_ARRAY:
6411                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
6412         case MONO_TYPE_PTR:
6413                 return mono_ptr_class_get (type->data.type);
6414         case MONO_TYPE_FNPTR:
6415                 return mono_fnptr_class_get (type->data.method);
6416         case MONO_TYPE_SZARRAY:
6417                 return mono_array_class_get (type->data.klass, 1);
6418         case MONO_TYPE_CLASS:
6419         case MONO_TYPE_VALUETYPE:
6420                 return type->data.klass;
6421         case MONO_TYPE_GENERICINST:
6422                 return mono_generic_class_get_class (type->data.generic_class);
6423         case MONO_TYPE_MVAR:
6424         case MONO_TYPE_VAR:
6425                 return mono_class_from_generic_parameter_internal (type->data.generic_param);
6426         default:
6427                 g_warning ("mono_class_from_mono_type: implement me 0x%02x\n", type->type);
6428                 g_assert_not_reached ();
6429         }
6430
6431         // Yes, this returns NULL, even if it is documented as not doing so, but there
6432         // is no way for the code to make it this far, due to the assert above.
6433         return NULL;
6434 }
6435
6436 /**
6437  * mono_type_retrieve_from_typespec
6438  * @image: context where the image is created
6439  * @type_spec:  typespec token
6440  * @context: the generic context used to evaluate generic instantiations in
6441  */
6442 static MonoType *
6443 mono_type_retrieve_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, gboolean *did_inflate, MonoError *error)
6444 {
6445         MonoType *t = mono_type_create_from_typespec_checked (image, type_spec, error);
6446
6447         *did_inflate = FALSE;
6448
6449         if (!t)
6450                 return NULL;
6451
6452         if (context && (context->class_inst || context->method_inst)) {
6453                 MonoType *inflated = inflate_generic_type (NULL, t, context, error);
6454
6455                 if (!mono_error_ok (error)) {
6456                         return NULL;
6457                 }
6458
6459                 if (inflated) {
6460                         t = inflated;
6461                         *did_inflate = TRUE;
6462                 }
6463         }
6464         return t;
6465 }
6466
6467 /**
6468  * mono_class_create_from_typespec
6469  * @image: context where the image is created
6470  * @type_spec:  typespec token
6471  * @context: the generic context used to evaluate generic instantiations in
6472  */
6473 static MonoClass *
6474 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec, MonoGenericContext *context, MonoError *error)
6475 {
6476         MonoClass *ret;
6477         gboolean inflated = FALSE;
6478         MonoType *t = mono_type_retrieve_from_typespec (image, type_spec, context, &inflated, error);
6479         return_val_if_nok (error, NULL);
6480         ret = mono_class_from_mono_type (t);
6481         if (inflated)
6482                 mono_metadata_free_type (t);
6483         return ret;
6484 }
6485
6486 /**
6487  * mono_bounded_array_class_get:
6488  * @element_class: element class 
6489  * @rank: the dimension of the array class
6490  * @bounded: whenever the array has non-zero bounds
6491  *
6492  * Returns: A class object describing the array with element type @element_type and 
6493  * dimension @rank. 
6494  */
6495 MonoClass *
6496 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
6497 {
6498         MonoImage *image;
6499         MonoClass *klass, *cached, *k;
6500         MonoClass *parent = NULL;
6501         GSList *list, *rootlist = NULL;
6502         int nsize;
6503         char *name;
6504
6505         g_assert (rank <= 255);
6506
6507         if (rank > 1)
6508                 /* bounded only matters for one-dimensional arrays */
6509                 bounded = FALSE;
6510
6511         image = eclass->image;
6512
6513         /* Check cache */
6514         cached = NULL;
6515         if (rank == 1 && !bounded) {
6516                 /*
6517                  * This case is very frequent not just during compilation because of calls
6518                  * from mono_class_from_mono_type (), mono_array_new (),
6519                  * Array:CreateInstance (), etc, so use a separate cache + a separate lock.
6520                  */
6521                 mono_os_mutex_lock (&image->szarray_cache_lock);
6522                 if (!image->szarray_cache)
6523                         image->szarray_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6524                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6525                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6526         } else {
6527                 mono_loader_lock ();
6528                 if (!image->array_cache)
6529                         image->array_cache = g_hash_table_new (mono_aligned_addr_hash, NULL);
6530                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6531                 for (list = rootlist; list; list = list->next) {
6532                         k = (MonoClass *)list->data;
6533                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6534                                 cached = k;
6535                                 break;
6536                         }
6537                 }
6538                 mono_loader_unlock ();
6539         }
6540         if (cached)
6541                 return cached;
6542
6543         parent = mono_defaults.array_class;
6544         if (!parent->inited)
6545                 mono_class_init (parent);
6546
6547         klass = (MonoClass *)mono_image_alloc0 (image, sizeof (MonoClassArray));
6548
6549         klass->image = image;
6550         klass->name_space = eclass->name_space;
6551         klass->class_kind = MONO_CLASS_ARRAY;
6552
6553         nsize = strlen (eclass->name);
6554         name = (char *)g_malloc (nsize + 2 + rank + 1);
6555         memcpy (name, eclass->name, nsize);
6556         name [nsize] = '[';
6557         if (rank > 1)
6558                 memset (name + nsize + 1, ',', rank - 1);
6559         if (bounded)
6560                 name [nsize + rank] = '*';
6561         name [nsize + rank + bounded] = ']';
6562         name [nsize + rank + bounded + 1] = 0;
6563         klass->name = mono_image_strdup (image, name);
6564         g_free (name);
6565
6566         klass->type_token = 0;
6567         klass->parent = parent;
6568         klass->instance_size = mono_class_instance_size (klass->parent);
6569
6570         if (eclass->byval_arg.type == MONO_TYPE_TYPEDBYREF || eclass->byval_arg.type == MONO_TYPE_VOID) {
6571                 /*Arrays of those two types are invalid.*/
6572                 MonoError prepared_error;
6573                 mono_error_init (&prepared_error);
6574                 mono_error_set_invalid_program (&prepared_error, "Arrays of void or System.TypedReference types are invalid.");
6575                 mono_class_set_failure (klass, mono_error_box (&prepared_error, klass->image));
6576                 mono_error_cleanup (&prepared_error);
6577         } else if (eclass->enumtype && !mono_class_enum_basetype (eclass)) {
6578                 guint32 ref_info_handle = mono_class_get_ref_info_handle (eclass);
6579                 if (!ref_info_handle || eclass->wastypebuilder) {
6580                         g_warning ("Only incomplete TypeBuilder objects are allowed to be an enum without base_type");
6581                         g_assert (ref_info_handle && !eclass->wastypebuilder);
6582                 }
6583                 /* element_size -1 is ok as this is not an instantitable type*/
6584                 klass->sizes.element_size = -1;
6585         } else
6586                 klass->sizes.element_size = mono_class_array_element_size (eclass);
6587
6588         mono_class_setup_supertypes (klass);
6589
6590         if (mono_class_is_ginst (eclass))
6591                 mono_class_init (eclass);
6592         if (!eclass->size_inited)
6593                 mono_class_setup_fields (eclass);
6594         mono_class_set_type_load_failure_causedby_class (klass, eclass, "Could not load array element type");
6595         /*FIXME we fail the array type, but we have to let other fields be set.*/
6596
6597         klass->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
6598
6599         klass->rank = rank;
6600         
6601         if (eclass->enumtype)
6602                 klass->cast_class = eclass->element_class;
6603         else
6604                 klass->cast_class = eclass;
6605
6606         switch (klass->cast_class->byval_arg.type) {
6607         case MONO_TYPE_I1:
6608                 klass->cast_class = mono_defaults.byte_class;
6609                 break;
6610         case MONO_TYPE_U2:
6611                 klass->cast_class = mono_defaults.int16_class;
6612                 break;
6613         case MONO_TYPE_U4:
6614 #if SIZEOF_VOID_P == 4
6615         case MONO_TYPE_I:
6616         case MONO_TYPE_U:
6617 #endif
6618                 klass->cast_class = mono_defaults.int32_class;
6619                 break;
6620         case MONO_TYPE_U8:
6621 #if SIZEOF_VOID_P == 8
6622         case MONO_TYPE_I:
6623         case MONO_TYPE_U:
6624 #endif
6625                 klass->cast_class = mono_defaults.int64_class;
6626                 break;
6627         default:
6628                 break;
6629         }
6630
6631         klass->element_class = eclass;
6632
6633         if ((rank > 1) || bounded) {
6634                 MonoArrayType *at = (MonoArrayType *)mono_image_alloc0 (image, sizeof (MonoArrayType));
6635                 klass->byval_arg.type = MONO_TYPE_ARRAY;
6636                 klass->byval_arg.data.array = at;
6637                 at->eklass = eclass;
6638                 at->rank = rank;
6639                 /* FIXME: complete.... */
6640         } else {
6641                 klass->byval_arg.type = MONO_TYPE_SZARRAY;
6642                 klass->byval_arg.data.klass = eclass;
6643         }
6644         klass->this_arg = klass->byval_arg;
6645         klass->this_arg.byref = 1;
6646
6647         mono_loader_lock ();
6648
6649         /* Check cache again */
6650         cached = NULL;
6651         if (rank == 1 && !bounded) {
6652                 mono_os_mutex_lock (&image->szarray_cache_lock);
6653                 cached = (MonoClass *)g_hash_table_lookup (image->szarray_cache, eclass);
6654                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6655         } else {
6656                 rootlist = (GSList *)g_hash_table_lookup (image->array_cache, eclass);
6657                 for (list = rootlist; list; list = list->next) {
6658                         k = (MonoClass *)list->data;
6659                         if ((k->rank == rank) && (k->byval_arg.type == (((rank > 1) || bounded) ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
6660                                 cached = k;
6661                                 break;
6662                         }
6663                 }
6664         }
6665         if (cached) {
6666                 mono_loader_unlock ();
6667                 return cached;
6668         }
6669
6670         mono_profiler_class_event (klass, MONO_PROFILE_START_LOAD);
6671
6672         classes_size += sizeof (MonoClassArray);
6673         ++class_array_count;
6674
6675         if (rank == 1 && !bounded) {
6676                 mono_os_mutex_lock (&image->szarray_cache_lock);
6677                 g_hash_table_insert (image->szarray_cache, eclass, klass);
6678                 mono_os_mutex_unlock (&image->szarray_cache_lock);
6679         } else {
6680                 list = g_slist_append (rootlist, klass);
6681                 g_hash_table_insert (image->array_cache, eclass, list);
6682         }
6683
6684         mono_loader_unlock ();
6685
6686         mono_profiler_class_loaded (klass, MONO_PROFILE_OK);
6687
6688         return klass;
6689 }
6690
6691 /**
6692  * mono_array_class_get:
6693  * @element_class: element class 
6694  * @rank: the dimension of the array class
6695  *
6696  * Returns: A class object describing the array with element type @element_type and 
6697  * dimension @rank. 
6698  */
6699 MonoClass *
6700 mono_array_class_get (MonoClass *eclass, guint32 rank)
6701 {
6702         return mono_bounded_array_class_get (eclass, rank, FALSE);
6703 }
6704
6705 /**
6706  * mono_class_instance_size:
6707  * @klass: a class 
6708  *
6709  * Use to get the size of a class in bytes.
6710  *
6711  * Returns: The size of an object instance
6712  */
6713 gint32
6714 mono_class_instance_size (MonoClass *klass)
6715 {       
6716         if (!klass->size_inited)
6717                 mono_class_init (klass);
6718
6719         return klass->instance_size;
6720 }
6721
6722 /**
6723  * mono_class_min_align:
6724  * @klass: a class 
6725  *
6726  * Use to get the computed minimum alignment requirements for the specified class.
6727  *
6728  * Returns: minimum alignment requirements
6729  */
6730 gint32
6731 mono_class_min_align (MonoClass *klass)
6732 {       
6733         if (!klass->size_inited)
6734                 mono_class_init (klass);
6735
6736         return klass->min_align;
6737 }
6738
6739 /**
6740  * mono_class_value_size:
6741  * @klass: a class 
6742  *
6743  * This function is used for value types, and return the
6744  * space and the alignment to store that kind of value object.
6745  *
6746  * Returns: the size of a value of kind @klass
6747  */
6748 gint32
6749 mono_class_value_size (MonoClass *klass, guint32 *align)
6750 {
6751         gint32 size;
6752
6753         /* fixme: check disable, because we still have external revereces to
6754          * mscorlib and Dummy Objects 
6755          */
6756         /*g_assert (klass->valuetype);*/
6757
6758         size = mono_class_instance_size (klass) - sizeof (MonoObject);
6759
6760         if (align)
6761                 *align = klass->min_align;
6762
6763         return size;
6764 }
6765
6766 /**
6767  * mono_class_data_size:
6768  * @klass: a class 
6769  * 
6770  * Returns: The size of the static class data
6771  */
6772 gint32
6773 mono_class_data_size (MonoClass *klass)
6774 {       
6775         if (!klass->inited)
6776                 mono_class_init (klass);
6777         /* This can happen with dynamically created types */
6778         if (!klass->fields_inited)
6779                 mono_class_setup_fields (klass);
6780
6781         /* in arrays, sizes.class_size is unioned with element_size
6782          * and arrays have no static fields
6783          */
6784         if (klass->rank)
6785                 return 0;
6786         return klass->sizes.class_size;
6787 }
6788
6789 /*
6790  * Auxiliary routine to mono_class_get_field
6791  *
6792  * Takes a field index instead of a field token.
6793  */
6794 static MonoClassField *
6795 mono_class_get_field_idx (MonoClass *klass, int idx)
6796 {
6797         mono_class_setup_fields (klass);
6798         if (mono_class_has_failure (klass))
6799                 return NULL;
6800
6801         while (klass) {
6802                 int first_field_idx = mono_class_get_first_field_idx (klass);
6803                 int fcount = mono_class_get_field_count (klass);
6804                 if (klass->image->uncompressed_metadata) {
6805                         /* 
6806                          * first_field_idx points to the FieldPtr table, while idx points into the
6807                          * Field table, so we have to do a search.
6808                          */
6809                         /*FIXME this is broken for types with multiple fields with the same name.*/
6810                         const char *name = mono_metadata_string_heap (klass->image, mono_metadata_decode_row_col (&klass->image->tables [MONO_TABLE_FIELD], idx, MONO_FIELD_NAME));
6811                         int i;
6812
6813                         for (i = 0; i < fcount; ++i)
6814                                 if (mono_field_get_name (&klass->fields [i]) == name)
6815                                         return &klass->fields [i];
6816                         g_assert_not_reached ();
6817                 } else {                        
6818                         if (fcount) {
6819                                 if ((idx >= first_field_idx) && (idx < first_field_idx + fcount)){
6820                                         return &klass->fields [idx - first_field_idx];
6821                                 }
6822                         }
6823                 }
6824                 klass = klass->parent;
6825         }
6826         return NULL;
6827 }
6828
6829 /**
6830  * mono_class_get_field:
6831  * @class: the class to lookup the field.
6832  * @field_token: the field token
6833  *
6834  * Returns: A MonoClassField representing the type and offset of
6835  * the field, or a NULL value if the field does not belong to this
6836  * class.
6837  */
6838 MonoClassField *
6839 mono_class_get_field (MonoClass *klass, guint32 field_token)
6840 {
6841         int idx = mono_metadata_token_index (field_token);
6842
6843         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
6844
6845         return mono_class_get_field_idx (klass, idx - 1);
6846 }
6847
6848 /**
6849  * mono_class_get_field_from_name:
6850  * @klass: the class to lookup the field.
6851  * @name: the field name
6852  *
6853  * Search the class @klass and it's parents for a field with the name @name.
6854  * 
6855  * Returns: The MonoClassField pointer of the named field or NULL
6856  */
6857 MonoClassField *
6858 mono_class_get_field_from_name (MonoClass *klass, const char *name)
6859 {
6860         return mono_class_get_field_from_name_full (klass, name, NULL);
6861 }
6862
6863 /**
6864  * mono_class_get_field_from_name_full:
6865  * @klass: the class to lookup the field.
6866  * @name: the field name
6867  * @type: the type of the fields. This optional.
6868  *
6869  * Search the class @klass and it's parents for a field with the name @name and type @type.
6870  *
6871  * If @klass is an inflated generic type, the type comparison is done with the equivalent field
6872  * of its generic type definition.
6873  *
6874  * Returns: The MonoClassField pointer of the named field or NULL
6875  */
6876 MonoClassField *
6877 mono_class_get_field_from_name_full (MonoClass *klass, const char *name, MonoType *type)
6878 {
6879         int i;
6880
6881         mono_class_setup_fields (klass);
6882         if (mono_class_has_failure (klass))
6883                 return NULL;
6884
6885         while (klass) {
6886                 int fcount = mono_class_get_field_count (klass);
6887                 for (i = 0; i < fcount; ++i) {
6888                         MonoClassField *field = &klass->fields [i];
6889
6890                         if (strcmp (name, mono_field_get_name (field)) != 0)
6891                                 continue;
6892
6893                         if (type) {
6894                                 MonoType *field_type = mono_metadata_get_corresponding_field_from_generic_type_definition (field)->type;
6895                                 if (!mono_metadata_type_equal_full (type, field_type, TRUE))
6896                                         continue;
6897                         }
6898                         return field;
6899                 }
6900                 klass = klass->parent;
6901         }
6902         return NULL;
6903 }
6904
6905 /**
6906  * mono_class_get_field_token:
6907  * @field: the field we need the token of
6908  *
6909  * Get the token of a field. Note that the tokesn is only valid for the image
6910  * the field was loaded from. Don't use this function for fields in dynamic types.
6911  * 
6912  * Returns: The token representing the field in the image it was loaded from.
6913  */
6914 guint32
6915 mono_class_get_field_token (MonoClassField *field)
6916 {
6917         MonoClass *klass = field->parent;
6918         int i;
6919
6920         mono_class_setup_fields (klass);
6921
6922         while (klass) {
6923                 if (!klass->fields)
6924                         return 0;
6925                 int first_field_idx = mono_class_get_first_field_idx (klass);
6926                 int fcount = mono_class_get_field_count (klass);
6927                 for (i = 0; i < fcount; ++i) {
6928                         if (&klass->fields [i] == field) {
6929                                 int idx = first_field_idx + i + 1;
6930
6931                                 if (klass->image->uncompressed_metadata)
6932                                         idx = mono_metadata_translate_token_index (klass->image, MONO_TABLE_FIELD, idx);
6933                                 return mono_metadata_make_token (MONO_TABLE_FIELD, idx);
6934                         }
6935                 }
6936                 klass = klass->parent;
6937         }
6938
6939         g_assert_not_reached ();
6940         return 0;
6941 }
6942
6943 static int
6944 mono_field_get_index (MonoClassField *field)
6945 {
6946         int index = field - field->parent->fields;
6947         g_assert (index >= 0 && index < mono_class_get_field_count (field->parent));
6948
6949         return index;
6950 }
6951
6952 /*
6953  * mono_class_get_field_default_value:
6954  *
6955  * Return the default value of the field as a pointer into the metadata blob.
6956  */
6957 const char*
6958 mono_class_get_field_default_value (MonoClassField *field, MonoTypeEnum *def_type)
6959 {
6960         guint32 cindex;
6961         guint32 constant_cols [MONO_CONSTANT_SIZE];
6962         int field_index;
6963         MonoClass *klass = field->parent;
6964         MonoFieldDefaultValue *def_values;
6965
6966         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT);
6967
6968         def_values = mono_class_get_field_def_values (klass);
6969         if (!def_values) {
6970                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
6971
6972                 mono_class_set_field_def_values (klass, def_values);
6973         }
6974
6975         field_index = mono_field_get_index (field);
6976                 
6977         if (!def_values [field_index].data) {
6978                 cindex = mono_metadata_get_constant_index (field->parent->image, mono_class_get_field_token (field), 0);
6979                 if (!cindex)
6980                         return NULL;
6981
6982                 g_assert (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA));
6983
6984                 mono_metadata_decode_row (&field->parent->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
6985                 def_values [field_index].def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
6986                 mono_memory_barrier ();
6987                 def_values [field_index].data = (const char *)mono_metadata_blob_heap (field->parent->image, constant_cols [MONO_CONSTANT_VALUE]);
6988         }
6989
6990         *def_type = def_values [field_index].def_type;
6991         return def_values [field_index].data;
6992 }
6993
6994 static int
6995 mono_property_get_index (MonoProperty *prop)
6996 {
6997         MonoClassPropertyInfo *info = mono_class_get_property_info (prop->parent);
6998         int index = prop - info->properties;
6999
7000         g_assert (index >= 0 && index < info->count);
7001
7002         return index;
7003 }
7004
7005 /*
7006  * mono_class_get_property_default_value:
7007  *
7008  * Return the default value of the field as a pointer into the metadata blob.
7009  */
7010 const char*
7011 mono_class_get_property_default_value (MonoProperty *property, MonoTypeEnum *def_type)
7012 {
7013         guint32 cindex;
7014         guint32 constant_cols [MONO_CONSTANT_SIZE];
7015         MonoClass *klass = property->parent;
7016
7017         g_assert (property->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT);
7018         /*
7019          * We don't cache here because it is not used by C# so it's quite rare, but
7020          * we still do the lookup in klass->ext because that is where the data
7021          * is stored for dynamic assemblies.
7022          */
7023
7024         if (image_is_dynamic (klass->image)) {
7025                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7026                 int prop_index = mono_property_get_index (property);
7027                 if (info->def_values && info->def_values [prop_index].data) {
7028                         *def_type = info->def_values [prop_index].def_type;
7029                         return info->def_values [prop_index].data;
7030                 }
7031                 return NULL;
7032         }
7033         cindex = mono_metadata_get_constant_index (klass->image, mono_class_get_property_token (property), 0);
7034         if (!cindex)
7035                 return NULL;
7036
7037         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_CONSTANT], cindex - 1, constant_cols, MONO_CONSTANT_SIZE);
7038         *def_type = (MonoTypeEnum)constant_cols [MONO_CONSTANT_TYPE];
7039         return (const char *)mono_metadata_blob_heap (klass->image, constant_cols [MONO_CONSTANT_VALUE]);
7040 }
7041
7042 guint32
7043 mono_class_get_event_token (MonoEvent *event)
7044 {
7045         MonoClass *klass = event->parent;
7046         int i;
7047
7048         while (klass) {
7049                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
7050                 if (info) {
7051                         for (i = 0; i < info->count; ++i) {
7052                                 if (&info->events [i] == event)
7053                                         return mono_metadata_make_token (MONO_TABLE_EVENT, info->first + i + 1);
7054                         }
7055                 }
7056                 klass = klass->parent;
7057         }
7058
7059         g_assert_not_reached ();
7060         return 0;
7061 }
7062
7063 /**
7064  * mono_class_get_property_from_name:
7065  * @klass: a class
7066  * @name: name of the property to lookup in the specified class
7067  *
7068  * Use this method to lookup a property in a class
7069  * Returns: the MonoProperty with the given name, or NULL if the property
7070  * does not exist on the @klass.
7071  */
7072 MonoProperty*
7073 mono_class_get_property_from_name (MonoClass *klass, const char *name)
7074 {
7075         while (klass) {
7076                 MonoProperty* p;
7077                 gpointer iter = NULL;
7078                 while ((p = mono_class_get_properties (klass, &iter))) {
7079                         if (! strcmp (name, p->name))
7080                                 return p;
7081                 }
7082                 klass = klass->parent;
7083         }
7084         return NULL;
7085 }
7086
7087 /**
7088  * mono_class_get_property_token:
7089  * @prop: MonoProperty to query
7090  *
7091  * Returns: The ECMA token for the specified property.
7092  */
7093 guint32
7094 mono_class_get_property_token (MonoProperty *prop)
7095 {
7096         MonoClass *klass = prop->parent;
7097         while (klass) {
7098                 MonoProperty* p;
7099                 int i = 0;
7100                 gpointer iter = NULL;
7101                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
7102                 while ((p = mono_class_get_properties (klass, &iter))) {
7103                         if (&info->properties [i] == prop)
7104                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, info->first + i + 1);
7105                         
7106                         i ++;
7107                 }
7108                 klass = klass->parent;
7109         }
7110
7111         g_assert_not_reached ();
7112         return 0;
7113 }
7114
7115 char *
7116 mono_class_name_from_token (MonoImage *image, guint32 type_token)
7117 {
7118         const char *name, *nspace;
7119         if (image_is_dynamic (image))
7120                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
7121         
7122         switch (type_token & 0xff000000){
7123         case MONO_TOKEN_TYPE_DEF: {
7124                 guint32 cols [MONO_TYPEDEF_SIZE];
7125                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
7126                 guint tidx = mono_metadata_token_index (type_token);
7127
7128                 if (tidx > tt->rows)
7129                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7130
7131                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
7132                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7133                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7134                 if (strlen (nspace) == 0)
7135                         return g_strdup_printf ("%s", name);
7136                 else
7137                         return g_strdup_printf ("%s.%s", nspace, name);
7138         }
7139
7140         case MONO_TOKEN_TYPE_REF: {
7141                 MonoError error;
7142                 guint32 cols [MONO_TYPEREF_SIZE];
7143                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7144                 guint tidx = mono_metadata_token_index (type_token);
7145
7146                 if (tidx > t->rows)
7147                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7148
7149                 if (!mono_verifier_verify_typeref_row (image, tidx - 1, &error)) {
7150                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7151                         mono_error_cleanup (&error);
7152                         return msg;
7153                 }
7154
7155                 mono_metadata_decode_row (t, tidx-1, cols, MONO_TYPEREF_SIZE);
7156                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
7157                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
7158                 if (strlen (nspace) == 0)
7159                         return g_strdup_printf ("%s", name);
7160                 else
7161                         return g_strdup_printf ("%s.%s", nspace, name);
7162         }
7163                 
7164         case MONO_TOKEN_TYPE_SPEC:
7165                 return g_strdup_printf ("Typespec 0x%08x", type_token);
7166         default:
7167                 return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7168         }
7169 }
7170
7171 static char *
7172 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
7173 {
7174         if (image_is_dynamic (image))
7175                 return g_strdup_printf ("DynamicAssembly %s", image->name);
7176         
7177         switch (type_token & 0xff000000){
7178         case MONO_TOKEN_TYPE_DEF:
7179                 if (image->assembly)
7180                         return mono_stringify_assembly_name (&image->assembly->aname);
7181                 else if (image->assembly_name)
7182                         return g_strdup (image->assembly_name);
7183                 return g_strdup_printf ("%s", image->name ? image->name : "[Could not resolve assembly name");
7184         case MONO_TOKEN_TYPE_REF: {
7185                 MonoError error;
7186                 MonoAssemblyName aname;
7187                 guint32 cols [MONO_TYPEREF_SIZE];
7188                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
7189                 guint32 idx = mono_metadata_token_index (type_token);
7190
7191                 if (idx > t->rows)
7192                         return g_strdup_printf ("Invalid type token 0x%08x", type_token);
7193         
7194                 if (!mono_verifier_verify_typeref_row (image, idx - 1, &error)) {
7195                         char *msg = g_strdup_printf ("Invalid type token 0x%08x due to '%s'", type_token, mono_error_get_message (&error));
7196                         mono_error_cleanup (&error);
7197                         return msg;
7198                 }
7199                 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPEREF_SIZE);
7200
7201                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLUTION_SCOPE_BITS;
7202                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLUTION_SCOPE_MASK) {
7203                 case MONO_RESOLUTION_SCOPE_MODULE:
7204                         /* FIXME: */
7205                         return g_strdup ("");
7206                 case MONO_RESOLUTION_SCOPE_MODULEREF:
7207                         /* FIXME: */
7208                         return g_strdup ("");
7209                 case MONO_RESOLUTION_SCOPE_TYPEREF:
7210                         /* FIXME: */
7211                         return g_strdup ("");
7212                 case MONO_RESOLUTION_SCOPE_ASSEMBLYREF:
7213                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
7214                         return mono_stringify_assembly_name (&aname);
7215                 default:
7216                         g_assert_not_reached ();
7217                 }
7218                 break;
7219         }
7220         case MONO_TOKEN_TYPE_SPEC:
7221                 /* FIXME: */
7222                 return g_strdup ("");
7223         default:
7224                 g_assert_not_reached ();
7225         }
7226
7227         return NULL;
7228 }
7229
7230 /**
7231  * mono_class_get_full:
7232  * @image: the image where the class resides
7233  * @type_token: the token for the class
7234  * @context: the generic context used to evaluate generic instantiations in
7235  * @deprecated: Functions that expose MonoGenericContext are going away in mono 4.0
7236  *
7237  * Returns: The MonoClass that represents @type_token in @image
7238  */
7239 MonoClass *
7240 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
7241 {
7242         MonoError error;
7243         MonoClass *klass;
7244         klass = mono_class_get_checked (image, type_token, &error);
7245
7246         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7247                 klass = mono_class_inflate_generic_class_checked (klass, context, &error);
7248
7249         g_assert (mono_error_ok (&error)); /* FIXME deprecate this function and forbit the runtime from using it. */
7250         return klass;
7251 }
7252
7253
7254 MonoClass *
7255 mono_class_get_and_inflate_typespec_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7256 {
7257         MonoClass *klass;
7258
7259         mono_error_init (error);
7260         klass = mono_class_get_checked (image, type_token, error);
7261
7262         if (klass && context && mono_metadata_token_table (type_token) == MONO_TABLE_TYPESPEC)
7263                 klass = mono_class_inflate_generic_class_checked (klass, context, error);
7264
7265         return klass;
7266 }
7267 /**
7268  * mono_class_get_checked:
7269  * @image: the image where the class resides
7270  * @type_token: the token for the class
7271  * @error: error object to return any error
7272  *
7273  * Returns: The MonoClass that represents @type_token in @image, or NULL on error.
7274  */
7275 MonoClass *
7276 mono_class_get_checked (MonoImage *image, guint32 type_token, MonoError *error)
7277 {
7278         MonoClass *klass = NULL;
7279
7280         mono_error_init (error);
7281
7282         if (image_is_dynamic (image)) {
7283                 int table = mono_metadata_token_table (type_token);
7284
7285                 if (table != MONO_TABLE_TYPEDEF && table != MONO_TABLE_TYPEREF && table != MONO_TABLE_TYPESPEC) {
7286                         mono_error_set_bad_image (error, image,"Bad token table for dynamic image: %x", table);
7287                         return NULL;
7288                 }
7289                 klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, NULL, error);
7290                 goto done;
7291         }
7292
7293         switch (type_token & 0xff000000){
7294         case MONO_TOKEN_TYPE_DEF:
7295                 klass = mono_class_create_from_typedef (image, type_token, error);
7296                 break;          
7297         case MONO_TOKEN_TYPE_REF:
7298                 klass = mono_class_from_typeref_checked (image, type_token, error);
7299                 break;
7300         case MONO_TOKEN_TYPE_SPEC:
7301                 klass = mono_class_create_from_typespec (image, type_token, NULL, error);
7302                 break;
7303         default:
7304                 mono_error_set_bad_image (error, image, "Unknown type token %x", type_token & 0xff000000);
7305         }
7306
7307 done:
7308         /* Generic case, should be avoided for when a better error is possible. */
7309         if (!klass && mono_error_ok (error)) {
7310                 char *name = mono_class_name_from_token (image, type_token);
7311                 char *assembly = mono_assembly_name_from_token (image, type_token);
7312                 mono_error_set_type_load_name (error, name, assembly, "Could not resolve type with token %08x", type_token);
7313         }
7314
7315         return klass;
7316 }
7317
7318
7319 /**
7320  * mono_type_get_checked:
7321  * @image: the image where the type resides
7322  * @type_token: the token for the type
7323  * @context: the generic context used to evaluate generic instantiations in
7324  * @error: Error handling context
7325  *
7326  * This functions exists to fullfill the fact that sometimes it's desirable to have access to the 
7327  * 
7328  * Returns: The MonoType that represents @type_token in @image
7329  */
7330 MonoType *
7331 mono_type_get_checked (MonoImage *image, guint32 type_token, MonoGenericContext *context, MonoError *error)
7332 {
7333         MonoType *type = NULL;
7334         gboolean inflated = FALSE;
7335
7336         mono_error_init (error);
7337
7338         //FIXME: this will not fix the very issue for which mono_type_get_full exists -but how to do it then?
7339         if (image_is_dynamic (image)) {
7340                 MonoClass *klass = (MonoClass *)mono_lookup_dynamic_token (image, type_token, context, error);
7341                 return_val_if_nok (error, NULL);
7342                 return mono_class_get_type (klass);
7343         }
7344
7345         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7346                 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7347
7348                 if (!klass) {
7349                         return NULL;
7350                 }
7351
7352                 g_assert (klass);
7353                 return mono_class_get_type (klass);
7354         }
7355
7356         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7357
7358         if (!type) {
7359                 return NULL;
7360         }
7361
7362         if (inflated) {
7363                 MonoType *tmp = type;
7364                 type = mono_class_get_type (mono_class_from_mono_type (type));
7365                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7366                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7367                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7368                  *
7369                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7370                  * */
7371                 if (type->type != tmp->type)
7372                         type = tmp;
7373                 else
7374                         mono_metadata_free_type (tmp);
7375         }
7376         return type;
7377 }
7378
7379 /**
7380  * mono_class_get:
7381  * @image: image where the class token will be looked up.
7382  * @type_token: a type token from the image
7383  *
7384  * Returns the MonoClass with the given @type_token on the @image
7385  */
7386 MonoClass *
7387 mono_class_get (MonoImage *image, guint32 type_token)
7388 {
7389         return mono_class_get_full (image, type_token, NULL);
7390 }
7391
7392 /**
7393  * mono_image_init_name_cache:
7394  *
7395  *  Initializes the class name cache stored in image->name_cache.
7396  *
7397  * LOCKING: Acquires the corresponding image lock.
7398  */
7399 void
7400 mono_image_init_name_cache (MonoImage *image)
7401 {
7402         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7403         guint32 cols [MONO_TYPEDEF_SIZE];
7404         const char *name;
7405         const char *nspace;
7406         guint32 i, visib, nspace_index;
7407         GHashTable *name_cache2, *nspace_table, *the_name_cache;
7408
7409         if (image->name_cache)
7410                 return;
7411
7412         the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7413
7414         if (image_is_dynamic (image)) {
7415                 mono_image_lock (image);
7416                 if (image->name_cache) {
7417                         /* Somebody initialized it before us */
7418                         g_hash_table_destroy (the_name_cache);
7419                 } else {
7420                         mono_atomic_store_release (&image->name_cache, the_name_cache);
7421                 }
7422                 mono_image_unlock (image);
7423                 return;
7424         }
7425
7426         /* Temporary hash table to avoid lookups in the nspace_table */
7427         name_cache2 = g_hash_table_new (NULL, NULL);
7428
7429         for (i = 1; i <= t->rows; ++i) {
7430                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7431                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7432                 /*
7433                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7434                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7435                  */
7436                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7437                         continue;
7438                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7439                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7440
7441                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7442                 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7443                 if (!nspace_table) {
7444                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7445                         g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7446                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7447                                                                  nspace_table);
7448                 }
7449                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7450         }
7451
7452         /* Load type names from EXPORTEDTYPES table */
7453         {
7454                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7455                 guint32 cols [MONO_EXP_TYPE_SIZE];
7456                 int i;
7457
7458                 for (i = 0; i < t->rows; ++i) {
7459                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7460
7461                         guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7462                         if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7463                                 /* Nested type */
7464                                 continue;
7465
7466                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7467                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7468
7469                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7470                         nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7471                         if (!nspace_table) {
7472                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7473                                 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7474                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7475                                                                          nspace_table);
7476                         }
7477                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7478                 }
7479         }
7480
7481         g_hash_table_destroy (name_cache2);
7482
7483         mono_image_lock (image);
7484         if (image->name_cache) {
7485                 /* Somebody initialized it before us */
7486                 g_hash_table_destroy (the_name_cache);
7487         } else {
7488                 mono_atomic_store_release (&image->name_cache, the_name_cache);
7489         }
7490         mono_image_unlock (image);
7491 }
7492
7493 /*FIXME Only dynamic assemblies should allow this operation.*/
7494 void
7495 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7496                                                           const char *name, guint32 index)
7497 {
7498         GHashTable *nspace_table;
7499         GHashTable *name_cache;
7500         guint32 old_index;
7501
7502         mono_image_init_name_cache (image);
7503         mono_image_lock (image);
7504
7505         name_cache = image->name_cache;
7506         if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7507                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7508                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7509         }
7510
7511         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7512                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7513
7514         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7515
7516         mono_image_unlock (image);
7517 }
7518
7519 typedef struct {
7520         gconstpointer key;
7521         gpointer value;
7522 } FindUserData;
7523
7524 static void
7525 find_nocase (gpointer key, gpointer value, gpointer user_data)
7526 {
7527         char *name = (char*)key;
7528         FindUserData *data = (FindUserData*)user_data;
7529
7530         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7531                 data->value = value;
7532 }
7533
7534 /**
7535  * mono_class_from_name_case:
7536  * @image: The MonoImage where the type is looked up in
7537  * @name_space: the type namespace
7538  * @name: the type short name.
7539  * @deprecated: use the mono_class_from_name_case_checked variant instead.
7540  *
7541  * Obtains a MonoClass with a given namespace and a given name which
7542  * is located in the given MonoImage.   The namespace and name
7543  * lookups are case insensitive.
7544  */
7545 MonoClass *
7546 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7547 {
7548         MonoError error;
7549         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7550         mono_error_cleanup (&error);
7551
7552         return res;
7553 }
7554
7555 /**
7556  * mono_class_from_name_case:
7557  * @image: The MonoImage where the type is looked up in
7558  * @name_space: the type namespace
7559  * @name: the type short name.
7560  * @error: if 
7561  *
7562  * Obtains a MonoClass with a given namespace and a given name which
7563  * is located in the given MonoImage.   The namespace and name
7564  * lookups are case insensitive.
7565  *
7566  * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7567  * was not found.   The @error object will contain information about the problem
7568  * in that case.
7569  */
7570 MonoClass *
7571 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7572 {
7573         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7574         guint32 cols [MONO_TYPEDEF_SIZE];
7575         const char *n;
7576         const char *nspace;
7577         guint32 i, visib;
7578
7579         mono_error_init (error);
7580
7581         if (image_is_dynamic (image)) {
7582                 guint32 token = 0;
7583                 FindUserData user_data;
7584
7585                 mono_image_init_name_cache (image);
7586                 mono_image_lock (image);
7587
7588                 user_data.key = name_space;
7589                 user_data.value = NULL;
7590                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7591
7592                 if (user_data.value) {
7593                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7594
7595                         user_data.key = name;
7596                         user_data.value = NULL;
7597
7598                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7599                         
7600                         if (user_data.value)
7601                                 token = GPOINTER_TO_UINT (user_data.value);
7602                 }
7603
7604                 mono_image_unlock (image);
7605                 
7606                 if (token)
7607                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7608                 else
7609                         return NULL;
7610
7611         }
7612
7613         /* add a cache if needed */
7614         for (i = 1; i <= t->rows; ++i) {
7615                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7616                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7617                 /*
7618                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7619                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7620                  */
7621                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7622                         continue;
7623                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7624                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7625                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7626                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7627         }
7628         return NULL;
7629 }
7630
7631 static MonoClass*
7632 return_nested_in (MonoClass *klass, char *nested)
7633 {
7634         MonoClass *found;
7635         char *s = strchr (nested, '/');
7636         gpointer iter = NULL;
7637
7638         if (s) {
7639                 *s = 0;
7640                 s++;
7641         }
7642
7643         while ((found = mono_class_get_nested_types (klass, &iter))) {
7644                 if (strcmp (found->name, nested) == 0) {
7645                         if (s)
7646                                 return return_nested_in (found, s);
7647                         return found;
7648                 }
7649         }
7650         return NULL;
7651 }
7652
7653 static MonoClass*
7654 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7655 {
7656         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7657         MonoImage *file_image;
7658         MonoClass *klass;
7659         int i;
7660
7661         mono_error_init (error);
7662
7663         /* 
7664          * The EXPORTEDTYPES table only contains public types, so have to search the
7665          * modules as well.
7666          * Note: image->modules contains the contents of the MODULEREF table, while
7667          * the real module list is in the FILE table.
7668          */
7669         for (i = 0; i < file_table->rows; i++) {
7670                 guint32 cols [MONO_FILE_SIZE];
7671                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7672                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7673                         continue;
7674
7675                 file_image = mono_image_load_file_for_image_checked (image, i + 1, error);
7676                 if (file_image) {
7677                         klass = mono_class_from_name_checked (file_image, name_space, name, error);
7678                         if (klass || !is_ok (error))
7679                                 return klass;
7680                 }
7681         }
7682
7683         return NULL;
7684 }
7685
7686 static MonoClass *
7687 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7688 {
7689         GHashTable *nspace_table;
7690         MonoImage *loaded_image;
7691         guint32 token = 0;
7692         int i;
7693         MonoClass *klass;
7694         char *nested;
7695         char buf [1024];
7696
7697         mono_error_init (error);
7698
7699         // Checking visited images avoids stack overflows when cyclic references exist.
7700         if (g_hash_table_lookup (visited_images, image))
7701                 return NULL;
7702
7703         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7704
7705         if ((nested = strchr (name, '/'))) {
7706                 int pos = nested - name;
7707                 int len = strlen (name);
7708                 if (len > 1023)
7709                         return NULL;
7710                 memcpy (buf, name, len + 1);
7711                 buf [pos] = 0;
7712                 nested = buf + pos + 1;
7713                 name = buf;
7714         }
7715
7716         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7717         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7718                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7719                 if (res) {
7720                         if (!klass) {
7721                                 klass = search_modules (image, name_space, name, error);
7722                                 if (!is_ok (error))
7723                                         return NULL;
7724                         }
7725                         if (nested)
7726                                 return klass ? return_nested_in (klass, nested) : NULL;
7727                         else
7728                                 return klass;
7729                 }
7730         }
7731
7732         mono_image_init_name_cache (image);
7733         mono_image_lock (image);
7734
7735         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7736
7737         if (nspace_table)
7738                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7739
7740         mono_image_unlock (image);
7741
7742         if (!token && image_is_dynamic (image) && image->modules) {
7743                 /* Search modules as well */
7744                 for (i = 0; i < image->module_count; ++i) {
7745                         MonoImage *module = image->modules [i];
7746
7747                         klass = mono_class_from_name_checked (module, name_space, name, error);
7748                         if (klass || !is_ok (error))
7749                                 return klass;
7750                 }
7751         }
7752
7753         if (!token) {
7754                 klass = search_modules (image, name_space, name, error);
7755                 if (klass || !is_ok (error))
7756                         return klass;
7757                 return NULL;
7758         }
7759
7760         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7761                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7762                 guint32 cols [MONO_EXP_TYPE_SIZE];
7763                 guint32 idx, impl;
7764
7765                 idx = mono_metadata_token_index (token);
7766
7767                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7768
7769                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7770                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7771                         loaded_image = mono_assembly_load_module_checked (image->assembly, impl >> MONO_IMPLEMENTATION_BITS, error);
7772                         if (!loaded_image)
7773                                 return NULL;
7774                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7775                         if (nested)
7776                                 return klass ? return_nested_in (klass, nested) : NULL;
7777                         return klass;
7778                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7779                         guint32 assembly_idx;
7780
7781                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7782
7783                         mono_assembly_load_reference (image, assembly_idx - 1);
7784                         g_assert (image->references [assembly_idx - 1]);
7785                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7786                                 return NULL;                    
7787                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7788                         if (nested)
7789                                 return klass ? return_nested_in (klass, nested) : NULL;
7790                         return klass;
7791                 } else {
7792                         g_assert_not_reached ();
7793                 }
7794         }
7795
7796         token = MONO_TOKEN_TYPE_DEF | token;
7797
7798         klass = mono_class_get_checked (image, token, error);
7799         if (nested)
7800                 return return_nested_in (klass, nested);
7801         return klass;
7802 }
7803
7804 /**
7805  * mono_class_from_name_checked:
7806  * @image: The MonoImage where the type is looked up in
7807  * @name_space: the type namespace
7808  * @name: the type short name.
7809  *
7810  * Obtains a MonoClass with a given namespace and a given name which
7811  * is located in the given MonoImage.
7812  *
7813  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7814  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7815  */
7816 MonoClass *
7817 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7818 {
7819         MonoClass *klass;
7820         GHashTable *visited_images;
7821
7822         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7823
7824         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7825
7826         g_hash_table_destroy (visited_images);
7827
7828         return klass;
7829 }
7830
7831 /**
7832  * mono_class_from_name:
7833  * @image: The MonoImage where the type is looked up in
7834  * @name_space: the type namespace
7835  * @name: the type short name.
7836  *
7837  * Obtains a MonoClass with a given namespace and a given name which
7838  * is located in the given MonoImage.
7839  *
7840  * To reference nested classes, use the "/" character as a separator.
7841  * For example use "Foo/Bar" to reference the class Bar that is nested
7842  * inside Foo, like this: "class Foo { class Bar {} }".
7843  */
7844 MonoClass *
7845 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
7846 {
7847         MonoError error;
7848         MonoClass *klass;
7849
7850         klass = mono_class_from_name_checked (image, name_space, name, &error);
7851         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
7852
7853         return klass;
7854 }
7855
7856 /**
7857  * mono_class_load_from_name:
7858  * @image: The MonoImage where the type is looked up in
7859  * @name_space: the type namespace
7860  * @name: the type short name.
7861  *
7862  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
7863  * This function should be used by the runtime for critical types to which there's no way to recover but crash
7864  * If they are missing. Thing of System.Object or System.String.
7865  */
7866 MonoClass *
7867 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
7868 {
7869         MonoError error;
7870         MonoClass *klass;
7871
7872         klass = mono_class_from_name_checked (image, name_space, name, &error);
7873         if (!klass)
7874                 g_error ("Runtime critical type %s.%s not found", name_space, name);
7875         if (!mono_error_ok (&error))
7876                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7877         return klass;
7878 }
7879
7880 /**
7881  * mono_class_try_load_from_name:
7882  * @image: The MonoImage where the type is looked up in
7883  * @name_space: the type namespace
7884  * @name: the type short name.
7885  *
7886  * This function tries to load a type, returning the class was found or NULL otherwise.
7887  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
7888  *
7889  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
7890  * a type that we would otherwise assume to be available but was not due some error.
7891  *
7892  */
7893 MonoClass*
7894 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
7895 {
7896         MonoError error;
7897         MonoClass *klass;
7898
7899         klass = mono_class_from_name_checked (image, name_space, name, &error);
7900         if (!mono_error_ok (&error))
7901                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
7902         return klass;
7903 }
7904
7905
7906 /**
7907  * mono_class_is_subclass_of:
7908  * @klass: class to probe if it is a subclass of another one
7909  * @klassc: the class we suspect is the base class
7910  * @check_interfaces: whether we should perform interface checks
7911  *
7912  * This method determines whether @klass is a subclass of @klassc.
7913  *
7914  * If the @check_interfaces flag is set, then if @klassc is an interface
7915  * this method return TRUE if the @klass implements the interface or
7916  * if @klass is an interface, if one of its base classes is @klass.
7917  *
7918  * If @check_interfaces is false then, then if @klass is not an interface
7919  * then it returns TRUE if the @klass is a subclass of @klassc.
7920  *
7921  * if @klass is an interface and @klassc is System.Object, then this function
7922  * return true.
7923  *
7924  */
7925 gboolean
7926 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
7927                            gboolean check_interfaces)
7928 {
7929         /* FIXME test for interfaces with variant generic arguments */
7930         mono_class_init (klass);
7931         mono_class_init (klassc);
7932         
7933         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
7934                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
7935                         return TRUE;
7936         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
7937                 int i;
7938
7939                 for (i = 0; i < klass->interface_count; i ++) {
7940                         MonoClass *ic =  klass->interfaces [i];
7941                         if (ic == klassc)
7942                                 return TRUE;
7943                 }
7944         } else {
7945                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
7946                         return TRUE;
7947         }
7948
7949         /* 
7950          * MS.NET thinks interfaces are a subclass of Object, so we think it as
7951          * well.
7952          */
7953         if (klassc == mono_defaults.object_class)
7954                 return TRUE;
7955
7956         return FALSE;
7957 }
7958
7959 static gboolean
7960 mono_type_is_generic_argument (MonoType *type)
7961 {
7962         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
7963 }
7964
7965 gboolean
7966 mono_class_has_variant_generic_params (MonoClass *klass)
7967 {
7968         int i;
7969         MonoGenericContainer *container;
7970
7971         if (!mono_class_is_ginst (klass))
7972                 return FALSE;
7973
7974         container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class);
7975
7976         for (i = 0; i < container->type_argc; ++i)
7977                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
7978                         return TRUE;
7979
7980         return FALSE;
7981 }
7982
7983 static gboolean
7984 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
7985 {
7986         if (target == candidate)
7987                 return TRUE;
7988
7989         if (check_for_reference_conv &&
7990                 mono_type_is_generic_argument (&target->byval_arg) &&
7991                 mono_type_is_generic_argument (&candidate->byval_arg)) {
7992                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
7993                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
7994
7995                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
7996                         return FALSE;
7997         }
7998         if (!mono_class_is_assignable_from (target, candidate))
7999                 return FALSE;
8000         return TRUE;
8001 }
8002
8003 /**
8004  * @container the generic container from the GTD
8005  * @klass: the class to be assigned to
8006  * @oklass: the source class
8007  * 
8008  * Both @klass and @oklass must be instances of the same generic interface.
8009  *
8010  * Returns: TRUE if @klass can be assigned to a @klass variable
8011  */
8012 gboolean
8013 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8014 {
8015         int j;
8016         MonoType **klass_argv, **oklass_argv;
8017         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8018         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8019
8020         if (klass == oklass)
8021                 return TRUE;
8022
8023         /*Viable candidates are instances of the same generic interface*/
8024         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8025                 return FALSE;
8026
8027         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8028         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8029
8030         for (j = 0; j < container->type_argc; ++j) {
8031                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8032                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8033
8034                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8035                         return FALSE;
8036
8037                 /*
8038                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8039                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8040                  */
8041                 if (param1_class != param2_class) {
8042                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8043                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8044                                         return FALSE;
8045                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8046                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8047                                         return FALSE;
8048                         } else
8049                                 return FALSE;
8050                 }
8051         }
8052         return TRUE;
8053 }
8054
8055 static gboolean
8056 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8057 {
8058         MonoGenericParam *gparam, *ogparam;
8059         MonoGenericParamInfo *tinfo, *cinfo;
8060         MonoClass **candidate_class;
8061         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8062         int tmask, cmask;
8063
8064         if (target == candidate)
8065                 return TRUE;
8066         if (target->byval_arg.type != candidate->byval_arg.type)
8067                 return FALSE;
8068
8069         gparam = target->byval_arg.data.generic_param;
8070         ogparam = candidate->byval_arg.data.generic_param;
8071         tinfo = mono_generic_param_info (gparam);
8072         cinfo = mono_generic_param_info (ogparam);
8073
8074         class_constraint_satisfied = FALSE;
8075         valuetype_constraint_satisfied = FALSE;
8076
8077         /*candidate must have a super set of target's special constraints*/
8078         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8079         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8080
8081         if (cinfo->constraints) {
8082                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8083                         MonoClass *cc = *candidate_class;
8084
8085                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8086                                 class_constraint_satisfied = TRUE;
8087                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8088                                 valuetype_constraint_satisfied = TRUE;
8089                 }
8090         }
8091         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8092         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8093
8094         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8095                 return FALSE;
8096         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8097                 return FALSE;
8098         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8099                 valuetype_constraint_satisfied)) {
8100                 return FALSE;
8101         }
8102
8103
8104         /*candidate type constraints must be a superset of target's*/
8105         if (tinfo->constraints) {
8106                 MonoClass **target_class;
8107                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8108                         MonoClass *tc = *target_class;
8109
8110                         /*
8111                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8112                          * check it's constraints since it satisfy the constraint by itself.
8113                          */
8114                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8115                                 continue;
8116
8117                         if (!cinfo->constraints)
8118                                 return FALSE;
8119
8120                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8121                                 MonoClass *cc = *candidate_class;
8122
8123                                 if (mono_class_is_assignable_from (tc, cc))
8124                                         break;
8125
8126                                 /*
8127                                  * This happens when we have the following:
8128                                  *
8129                                  * Bar<K> where K : IFace
8130                                  * Foo<T, U> where T : U where U : IFace
8131                                  *      ...
8132                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8133                                  *
8134                                  */
8135                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8136                                         if (mono_gparam_is_assignable_from (target, cc))
8137                                                 break;
8138                                 }
8139                         }
8140                         if (!*candidate_class)
8141                                 return FALSE;
8142                 }
8143         }
8144
8145         /*candidate itself must have a constraint that satisfy target*/
8146         if (cinfo->constraints) {
8147                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8148                         MonoClass *cc = *candidate_class;
8149                         if (mono_class_is_assignable_from (target, cc))
8150                                 return TRUE;
8151                 }
8152         }
8153         return FALSE;
8154 }
8155
8156 /**
8157  * mono_class_is_assignable_from:
8158  * @klass: the class to be assigned to
8159  * @oklass: the source class
8160  *
8161  * Returns: TRUE if an instance of object oklass can be assigned to an
8162  * instance of object @klass
8163  */
8164 gboolean
8165 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8166 {
8167         MonoError error;
8168         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8169         if (!klass->inited)
8170                 mono_class_init (klass);
8171
8172         if (!oklass->inited)
8173                 mono_class_init (oklass);
8174
8175         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8176                 return FALSE;
8177
8178         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8179                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8180                         return FALSE;
8181                 return mono_gparam_is_assignable_from (klass, oklass);
8182         }
8183
8184         if (MONO_CLASS_IS_INTERFACE (klass)) {
8185                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8186                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8187                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8188                         int i;
8189
8190                         if (constraints) {
8191                                 for (i = 0; constraints [i]; ++i) {
8192                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8193                                                 return TRUE;
8194                                 }
8195                         }
8196
8197                         return FALSE;
8198                 }
8199
8200                 /* interface_offsets might not be set for dynamic classes */
8201                 if (mono_class_get_ref_info_handle (oklass) && !oklass->interface_bitmap) {
8202                         /* 
8203                          * oklass might be a generic type parameter but they have 
8204                          * interface_offsets set.
8205                          */
8206                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8207                         if (!is_ok (&error)) {
8208                                 mono_error_cleanup (&error);
8209                                 return FALSE;
8210                         }
8211                         return result;
8212                 }
8213                 if (!oklass->interface_bitmap)
8214                         /* Happens with generic instances of not-yet created dynamic types */
8215                         return FALSE;
8216                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8217                         return TRUE;
8218
8219                 if (klass->is_array_special_interface && oklass->rank == 1) {
8220                         //XXX we could offset this by having the cast target computed at JIT time
8221                         //XXX we could go even further and emit a wrapper that would do the extra type check
8222                         MonoClass *iface_klass = mono_class_from_mono_type (mono_class_get_generic_class (klass)->context.class_inst->type_argv [0]);
8223                         MonoClass *obj_klass = oklass->cast_class; //This gets us the cast class of element type of the array
8224
8225                         // 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
8226                         // We can't apply it for ref types as this would go wrong with arrays - IList<byte[]> would have byte tested
8227                         if (iface_klass->valuetype)
8228                                 iface_klass = iface_klass->cast_class;
8229
8230                         //array covariant casts only operates on scalar to scalar
8231                         //This is so int[] can't be casted to IComparable<int>[]
8232                         if (!(obj_klass->valuetype && !iface_klass->valuetype) && mono_class_is_assignable_from (iface_klass, obj_klass))
8233                                 return TRUE;
8234                 }
8235
8236                 if (mono_class_has_variant_generic_params (klass)) {
8237                         int i;
8238                         mono_class_setup_interfaces (oklass, &error);
8239                         if (!mono_error_ok (&error)) {
8240                                 mono_error_cleanup (&error);
8241                                 return FALSE;
8242                         }
8243
8244                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8245                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8246                                 MonoClass *iface = oklass->interfaces_packed [i];
8247
8248                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8249                                         return TRUE;
8250                         }
8251                 }
8252                 return FALSE;
8253         } else if (klass->delegate) {
8254                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8255                         return TRUE;
8256         }else if (klass->rank) {
8257                 MonoClass *eclass, *eoclass;
8258
8259                 if (oklass->rank != klass->rank)
8260                         return FALSE;
8261
8262                 /* vectors vs. one dimensional arrays */
8263                 if (oklass->byval_arg.type != klass->byval_arg.type)
8264                         return FALSE;
8265
8266                 eclass = klass->cast_class;
8267                 eoclass = oklass->cast_class;
8268
8269                 /* 
8270                  * a is b does not imply a[] is b[] when a is a valuetype, and
8271                  * b is a reference type.
8272                  */
8273
8274                 if (eoclass->valuetype) {
8275                         if ((eclass == mono_defaults.enum_class) || 
8276                                 (eclass == mono_defaults.enum_class->parent) ||
8277                                 (eclass == mono_defaults.object_class))
8278                                 return FALSE;
8279                 }
8280
8281                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8282         } else if (mono_class_is_nullable (klass)) {
8283                 if (mono_class_is_nullable (oklass))
8284                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8285                 else
8286                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8287         } else if (klass == mono_defaults.object_class)
8288                 return TRUE;
8289
8290         return mono_class_has_parent (oklass, klass);
8291 }       
8292
8293 /*Check if @oklass is variant compatible with @klass.*/
8294 static gboolean
8295 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8296 {
8297         int j;
8298         MonoType **klass_argv, **oklass_argv;
8299         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8300         MonoGenericContainer *container = mono_class_get_generic_container (klass_gtd);
8301
8302         /*Viable candidates are instances of the same generic interface*/
8303         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8304                 return FALSE;
8305
8306         klass_argv = &mono_class_get_generic_class (klass)->context.class_inst->type_argv [0];
8307         oklass_argv = &mono_class_get_generic_class (oklass)->context.class_inst->type_argv [0];
8308
8309         for (j = 0; j < container->type_argc; ++j) {
8310                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8311                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8312
8313                 if (param1_class->valuetype != param2_class->valuetype)
8314                         return FALSE;
8315
8316                 /*
8317                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8318                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8319                  */
8320                 if (param1_class != param2_class) {
8321                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8322                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8323                                         return FALSE;
8324                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8325                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8326                                         return FALSE;
8327                         } else
8328                                 return FALSE;
8329                 }
8330         }
8331         return TRUE;
8332 }
8333 /*Check if @candidate implements the interface @target*/
8334 static gboolean
8335 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8336 {
8337         MonoError error;
8338         int i;
8339         gboolean is_variant = mono_class_has_variant_generic_params (target);
8340
8341         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8342                 if (mono_class_is_variant_compatible_slow (target, candidate))
8343                         return TRUE;
8344         }
8345
8346         do {
8347                 if (candidate == target)
8348                         return TRUE;
8349
8350                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8351                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8352                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8353                         int j;
8354                         if (tb && tb->interfaces) {
8355                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8356                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8357                                         MonoClass *iface_class;
8358
8359                                         /* we can't realize the type here since it can do pretty much anything. */
8360                                         if (!iface->type)
8361                                                 continue;
8362                                         iface_class = mono_class_from_mono_type (iface->type);
8363                                         if (iface_class == target)
8364                                                 return TRUE;
8365                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8366                                                 return TRUE;
8367                                         if (mono_class_implement_interface_slow (target, iface_class))
8368                                                 return TRUE;
8369                                 }
8370                         }
8371                 } else {
8372                         /*setup_interfaces don't mono_class_init anything*/
8373                         /*FIXME this doesn't handle primitive type arrays.
8374                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8375                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8376                         */
8377                         mono_class_setup_interfaces (candidate, &error);
8378                         if (!mono_error_ok (&error)) {
8379                                 mono_error_cleanup (&error);
8380                                 return FALSE;
8381                         }
8382
8383                         for (i = 0; i < candidate->interface_count; ++i) {
8384                                 if (candidate->interfaces [i] == target)
8385                                         return TRUE;
8386                                 
8387                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8388                                         return TRUE;
8389
8390                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8391                                         return TRUE;
8392                         }
8393                 }
8394                 candidate = candidate->parent;
8395         } while (candidate);
8396
8397         return FALSE;
8398 }
8399
8400 /*
8401  * Check if @oklass can be assigned to @klass.
8402  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8403  */
8404 gboolean
8405 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8406 {
8407         if (candidate == target)
8408                 return TRUE;
8409         if (target == mono_defaults.object_class)
8410                 return TRUE;
8411
8412         if (mono_class_has_parent (candidate, target))
8413                 return TRUE;
8414
8415         /*If target is not an interface there is no need to check them.*/
8416         if (MONO_CLASS_IS_INTERFACE (target))
8417                 return mono_class_implement_interface_slow (target, candidate);
8418
8419         if (target->delegate && mono_class_has_variant_generic_params (target))
8420                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8421
8422         if (target->rank) {
8423                 MonoClass *eclass, *eoclass;
8424
8425                 if (target->rank != candidate->rank)
8426                         return FALSE;
8427
8428                 /* vectors vs. one dimensional arrays */
8429                 if (target->byval_arg.type != candidate->byval_arg.type)
8430                         return FALSE;
8431
8432                 eclass = target->cast_class;
8433                 eoclass = candidate->cast_class;
8434
8435                 /*
8436                  * a is b does not imply a[] is b[] when a is a valuetype, and
8437                  * b is a reference type.
8438                  */
8439
8440                 if (eoclass->valuetype) {
8441                         if ((eclass == mono_defaults.enum_class) ||
8442                                 (eclass == mono_defaults.enum_class->parent) ||
8443                                 (eclass == mono_defaults.object_class))
8444                                 return FALSE;
8445                 }
8446
8447                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8448         }
8449         /*FIXME properly handle nullables */
8450         /*FIXME properly handle (M)VAR */
8451         return FALSE;
8452 }
8453
8454 /**
8455  * mono_class_get_cctor:
8456  * @klass: A MonoClass pointer
8457  *
8458  * Returns: The static constructor of @klass if it exists, NULL otherwise.
8459  */
8460 MonoMethod*
8461 mono_class_get_cctor (MonoClass *klass)
8462 {
8463         MonoCachedClassInfo cached_info;
8464
8465         if (image_is_dynamic (klass->image)) {
8466                 /* 
8467                  * has_cctor is not set for these classes because mono_class_init () is
8468                  * not run for them.
8469                  */
8470                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8471         }
8472
8473         mono_class_init (klass);
8474
8475         if (!klass->has_cctor)
8476                 return NULL;
8477
8478         if (mono_class_is_ginst (klass) && !klass->methods)
8479                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (mono_class_get_generic_class (klass)->container_class));
8480
8481         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8482                 MonoError error;
8483                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8484                 if (!mono_error_ok (&error))
8485                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8486                 return result;
8487         }
8488
8489         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8490 }
8491
8492 /**
8493  * mono_class_get_finalizer:
8494  * @klass: The MonoClass pointer
8495  *
8496  * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8497  */
8498 MonoMethod*
8499 mono_class_get_finalizer (MonoClass *klass)
8500 {
8501         MonoCachedClassInfo cached_info;
8502
8503         if (!klass->inited)
8504                 mono_class_init (klass);
8505         if (!mono_class_has_finalizer (klass))
8506                 return NULL;
8507
8508         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8509                 MonoError error;
8510                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8511                 if (!mono_error_ok (&error))
8512                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8513                 return result;
8514         }else {
8515                 mono_class_setup_vtable (klass);
8516                 return klass->vtable [finalize_slot];
8517         }
8518 }
8519
8520 /**
8521  * mono_class_needs_cctor_run:
8522  * @klass: the MonoClass pointer
8523  * @caller: a MonoMethod describing the caller
8524  *
8525  * Determines whenever the class has a static constructor and whenever it
8526  * needs to be called when executing CALLER.
8527  */
8528 gboolean
8529 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8530 {
8531         MonoMethod *method;
8532
8533         method = mono_class_get_cctor (klass);
8534         if (method)
8535                 return (method == caller) ? FALSE : TRUE;
8536         else
8537                 return FALSE;
8538 }
8539
8540 /**
8541  * mono_class_array_element_size:
8542  * @klass: 
8543  *
8544  * Returns: The number of bytes an element of type @klass
8545  * uses when stored into an array.
8546  */
8547 gint32
8548 mono_class_array_element_size (MonoClass *klass)
8549 {
8550         MonoType *type = &klass->byval_arg;
8551         
8552 handle_enum:
8553         switch (type->type) {
8554         case MONO_TYPE_I1:
8555         case MONO_TYPE_U1:
8556         case MONO_TYPE_BOOLEAN:
8557                 return 1;
8558         case MONO_TYPE_I2:
8559         case MONO_TYPE_U2:
8560         case MONO_TYPE_CHAR:
8561                 return 2;
8562         case MONO_TYPE_I4:
8563         case MONO_TYPE_U4:
8564         case MONO_TYPE_R4:
8565                 return 4;
8566         case MONO_TYPE_I:
8567         case MONO_TYPE_U:
8568         case MONO_TYPE_PTR:
8569         case MONO_TYPE_CLASS:
8570         case MONO_TYPE_STRING:
8571         case MONO_TYPE_OBJECT:
8572         case MONO_TYPE_SZARRAY:
8573         case MONO_TYPE_ARRAY: 
8574                 return sizeof (gpointer);
8575         case MONO_TYPE_I8:
8576         case MONO_TYPE_U8:
8577         case MONO_TYPE_R8:
8578                 return 8;
8579         case MONO_TYPE_VALUETYPE:
8580                 if (type->data.klass->enumtype) {
8581                         type = mono_class_enum_basetype (type->data.klass);
8582                         klass = klass->element_class;
8583                         goto handle_enum;
8584                 }
8585                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8586         case MONO_TYPE_GENERICINST:
8587                 type = &type->data.generic_class->container_class->byval_arg;
8588                 goto handle_enum;
8589         case MONO_TYPE_VAR:
8590         case MONO_TYPE_MVAR: {
8591                 int align;
8592
8593                 return mono_type_size (type, &align);
8594         }
8595         case MONO_TYPE_VOID:
8596                 return 0;
8597                 
8598         default:
8599                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8600         }
8601         return -1;
8602 }
8603
8604 /**
8605  * mono_array_element_size:
8606  * @ac: pointer to a #MonoArrayClass
8607  *
8608  * Returns: The size of single array element.
8609  */
8610 gint32
8611 mono_array_element_size (MonoClass *ac)
8612 {
8613         g_assert (ac->rank);
8614         return ac->sizes.element_size;
8615 }
8616
8617 gpointer
8618 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8619               MonoGenericContext *context)
8620 {
8621         MonoError error;
8622         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8623         g_assert (mono_error_ok (&error));
8624         return res;
8625 }
8626
8627 gpointer
8628 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8629               MonoGenericContext *context, MonoError *error)
8630 {
8631         mono_error_init (error);
8632
8633         if (image_is_dynamic (image)) {
8634                 MonoClass *tmp_handle_class;
8635                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context, error);
8636
8637                 mono_error_assert_ok (error);
8638                 g_assert (tmp_handle_class);
8639                 if (handle_class)
8640                         *handle_class = tmp_handle_class;
8641
8642                 if (tmp_handle_class == mono_defaults.typehandle_class)
8643                         return &((MonoClass*)obj)->byval_arg;
8644                 else
8645                         return obj;
8646         }
8647
8648         switch (token & 0xff000000) {
8649         case MONO_TOKEN_TYPE_DEF:
8650         case MONO_TOKEN_TYPE_REF:
8651         case MONO_TOKEN_TYPE_SPEC: {
8652                 MonoType *type;
8653                 if (handle_class)
8654                         *handle_class = mono_defaults.typehandle_class;
8655                 type = mono_type_get_checked (image, token, context, error);
8656                 if (!type)
8657                         return NULL;
8658
8659                 mono_class_init (mono_class_from_mono_type (type));
8660                 /* We return a MonoType* as handle */
8661                 return type;
8662         }
8663         case MONO_TOKEN_FIELD_DEF: {
8664                 MonoClass *klass;
8665                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8666                 if (!type) {
8667                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8668                         return NULL;
8669                 }
8670                 if (handle_class)
8671                         *handle_class = mono_defaults.fieldhandle_class;
8672                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8673                 if (!klass)
8674                         return NULL;
8675
8676                 mono_class_init (klass);
8677                 return mono_class_get_field (klass, token);
8678         }
8679         case MONO_TOKEN_METHOD_DEF:
8680         case MONO_TOKEN_METHOD_SPEC: {
8681                 MonoMethod *meth;
8682                 meth = mono_get_method_checked (image, token, NULL, context, error);
8683                 if (handle_class)
8684                         *handle_class = mono_defaults.methodhandle_class;
8685                 if (!meth)
8686                         return NULL;
8687
8688                 return meth;
8689         }
8690         case MONO_TOKEN_MEMBER_REF: {
8691                 guint32 cols [MONO_MEMBERREF_SIZE];
8692                 const char *sig;
8693                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8694                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8695                 mono_metadata_decode_blob_size (sig, &sig);
8696                 if (*sig == 0x6) { /* it's a field */
8697                         MonoClass *klass;
8698                         MonoClassField *field;
8699                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8700                         if (handle_class)
8701                                 *handle_class = mono_defaults.fieldhandle_class;
8702                         return field;
8703                 } else {
8704                         MonoMethod *meth;
8705                         meth = mono_get_method_checked (image, token, NULL, context, error);
8706                         if (handle_class)
8707                                 *handle_class = mono_defaults.methodhandle_class;
8708                         return meth;
8709                 }
8710         }
8711         default:
8712                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8713         }
8714         return NULL;
8715 }
8716
8717 gpointer
8718 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context, MonoError *error)
8719 {
8720         MonoClass *handle_class;
8721         mono_error_init (error);
8722         return mono_reflection_lookup_dynamic_token (image, token, TRUE, &handle_class, context, error);
8723 }
8724
8725 gpointer
8726 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error)
8727 {
8728         return mono_reflection_lookup_dynamic_token (image, token, valid_token, handle_class, context, error);
8729 }
8730
8731 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8732
8733 void
8734 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8735 {
8736         get_cached_class_info = func;
8737 }
8738
8739 static gboolean
8740 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8741 {
8742         if (!get_cached_class_info)
8743                 return FALSE;
8744         else
8745                 return get_cached_class_info (klass, res);
8746 }
8747
8748 void
8749 mono_install_get_class_from_name (MonoGetClassFromName func)
8750 {
8751         get_class_from_name = func;
8752 }
8753
8754 /**
8755  * mono_class_get_image:
8756  *
8757  * Use this method to get the `MonoImage*` where this class came from.
8758  *
8759  * Returns: The image where this class is defined.
8760  */
8761 MonoImage*
8762 mono_class_get_image (MonoClass *klass)
8763 {
8764         return klass->image;
8765 }
8766
8767 /**
8768  * mono_class_get_element_class:
8769  * @klass: the MonoClass to act on
8770  *
8771  * Use this function to get the element class of an array.
8772  *
8773  * Returns: The element class of an array.
8774  */
8775 MonoClass*
8776 mono_class_get_element_class (MonoClass *klass)
8777 {
8778         return klass->element_class;
8779 }
8780
8781 /**
8782  * mono_class_is_valuetype:
8783  * @klass: the MonoClass to act on
8784  *
8785  * Use this method to determine if the provided `MonoClass*` represents a value type,
8786  * or a reference type.
8787  *
8788  * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8789  */
8790 gboolean
8791 mono_class_is_valuetype (MonoClass *klass)
8792 {
8793         return klass->valuetype;
8794 }
8795
8796 /**
8797  * mono_class_is_enum:
8798  * @klass: the MonoClass to act on
8799  *
8800  * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8801  *
8802  * Returns: TRUE if the MonoClass represents an enumeration.
8803  */
8804 gboolean
8805 mono_class_is_enum (MonoClass *klass)
8806 {
8807         return klass->enumtype;
8808 }
8809
8810 /**
8811  * mono_class_enum_basetype:
8812  * @klass: the MonoClass to act on
8813  *
8814  * Use this function to get the underlying type for an enumeration value.
8815  * 
8816  * Returns: The underlying type representation for an enumeration.
8817  */
8818 MonoType*
8819 mono_class_enum_basetype (MonoClass *klass)
8820 {
8821         if (klass->element_class == klass)
8822                 /* SRE or broken types */
8823                 return NULL;
8824         else
8825                 return &klass->element_class->byval_arg;
8826 }
8827
8828 /**
8829  * mono_class_get_parent
8830  * @klass: the MonoClass to act on
8831  *
8832  * Returns: The parent class for this class.
8833  */
8834 MonoClass*
8835 mono_class_get_parent (MonoClass *klass)
8836 {
8837         return klass->parent;
8838 }
8839
8840 /**
8841  * mono_class_get_nesting_type:
8842  * @klass: the MonoClass to act on
8843  *
8844  * Use this function to obtain the class that the provided `MonoClass*` is nested on.
8845  *
8846  * If the return is NULL, this indicates that this class is not nested.
8847  *
8848  * Returns: The container type where this type is nested or NULL if this type is not a nested type.
8849  */
8850 MonoClass*
8851 mono_class_get_nesting_type (MonoClass *klass)
8852 {
8853         return klass->nested_in;
8854 }
8855
8856 /**
8857  * mono_class_get_rank:
8858  * @klass: the MonoClass to act on
8859  *
8860  * Returns: The rank for the array (the number of dimensions).
8861  */
8862 int
8863 mono_class_get_rank (MonoClass *klass)
8864 {
8865         return klass->rank;
8866 }
8867
8868 /**
8869  * mono_class_get_name
8870  * @klass: the MonoClass to act on
8871  *
8872  * Returns: The name of the class.
8873  */
8874 const char*
8875 mono_class_get_name (MonoClass *klass)
8876 {
8877         return klass->name;
8878 }
8879
8880 /**
8881  * mono_class_get_namespace:
8882  * @klass: the MonoClass to act on
8883  *
8884  * Returns: The namespace of the class.
8885  */
8886 const char*
8887 mono_class_get_namespace (MonoClass *klass)
8888 {
8889         return klass->name_space;
8890 }
8891
8892 /**
8893  * mono_class_get_type:
8894  * @klass: the MonoClass to act on
8895  *
8896  * This method returns the internal Type representation for the class.
8897  *
8898  * Returns: The MonoType from the class.
8899  */
8900 MonoType*
8901 mono_class_get_type (MonoClass *klass)
8902 {
8903         return &klass->byval_arg;
8904 }
8905
8906 /**
8907  * mono_class_get_type_token:
8908  * @klass: the MonoClass to act on
8909  *
8910  * This method returns type token for the class.
8911  *
8912  * Returns: The type token for the class.
8913  */
8914 guint32
8915 mono_class_get_type_token (MonoClass *klass)
8916 {
8917   return klass->type_token;
8918 }
8919
8920 /**
8921  * mono_class_get_byref_type:
8922  * @klass: the MonoClass to act on
8923  *
8924  * 
8925  */
8926 MonoType*
8927 mono_class_get_byref_type (MonoClass *klass)
8928 {
8929         return &klass->this_arg;
8930 }
8931
8932 /**
8933  * mono_class_num_fields:
8934  * @klass: the MonoClass to act on
8935  *
8936  * Returns: The number of static and instance fields in the class.
8937  */
8938 int
8939 mono_class_num_fields (MonoClass *klass)
8940 {
8941         return mono_class_get_field_count (klass);
8942 }
8943
8944 /**
8945  * mono_class_num_methods:
8946  * @klass: the MonoClass to act on
8947  *
8948  * Returns: The number of methods in the class.
8949  */
8950 int
8951 mono_class_num_methods (MonoClass *klass)
8952 {
8953         return mono_class_get_method_count (klass);
8954 }
8955
8956 /**
8957  * mono_class_num_properties
8958  * @klass: the MonoClass to act on
8959  *
8960  * Returns: The number of properties in the class.
8961  */
8962 int
8963 mono_class_num_properties (MonoClass *klass)
8964 {
8965         mono_class_setup_properties (klass);
8966
8967         return mono_class_get_property_info (klass)->count;
8968 }
8969
8970 /**
8971  * mono_class_num_events:
8972  * @klass: the MonoClass to act on
8973  *
8974  * Returns: The number of events in the class.
8975  */
8976 int
8977 mono_class_num_events (MonoClass *klass)
8978 {
8979         mono_class_setup_events (klass);
8980
8981         return mono_class_get_event_info (klass)->count;
8982 }
8983
8984 /**
8985  * mono_class_get_fields:
8986  * @klass: the MonoClass to act on
8987  *
8988  * This routine is an iterator routine for retrieving the fields in a class.
8989  *
8990  * You must pass a gpointer that points to zero and is treated as an opaque handle to
8991  * iterate over all of the elements.  When no more values are
8992  * available, the return value is NULL.
8993  *
8994  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
8995  */
8996 MonoClassField*
8997 mono_class_get_fields (MonoClass* klass, gpointer *iter)
8998 {
8999         MonoClassField* field;
9000         if (!iter)
9001                 return NULL;
9002         if (!*iter) {
9003                 mono_class_setup_fields (klass);
9004                 if (mono_class_has_failure (klass))
9005                         return NULL;
9006                 /* start from the first */
9007                 if (mono_class_get_field_count (klass)) {
9008                         *iter = &klass->fields [0];
9009                         return &klass->fields [0];
9010                 } else {
9011                         /* no fields */
9012                         return NULL;
9013                 }
9014         }
9015         field = (MonoClassField *)*iter;
9016         field++;
9017         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
9018                 *iter = field;
9019                 return field;
9020         }
9021         return NULL;
9022 }
9023
9024 /**
9025  * mono_class_get_methods
9026  * @klass: the MonoClass to act on
9027  *
9028  * This routine is an iterator routine for retrieving the fields in a class.
9029  *
9030  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9031  * iterate over all of the elements.  When no more values are
9032  * available, the return value is NULL.
9033  *
9034  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9035  */
9036 MonoMethod*
9037 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9038 {
9039         MonoMethod** method;
9040         if (!iter)
9041                 return NULL;
9042         if (!*iter) {
9043                 mono_class_setup_methods (klass);
9044
9045                 /*
9046                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9047                  * FIXME we should better report this error to the caller
9048                  */
9049                 if (!klass->methods)
9050                         return NULL;
9051                 /* start from the first */
9052                 if (mono_class_get_method_count (klass)) {
9053                         *iter = &klass->methods [0];
9054                         return klass->methods [0];
9055                 } else {
9056                         /* no method */
9057                         return NULL;
9058                 }
9059         }
9060         method = (MonoMethod **)*iter;
9061         method++;
9062         if (method < &klass->methods [mono_class_get_method_count (klass)]) {
9063                 *iter = method;
9064                 return *method;
9065         }
9066         return NULL;
9067 }
9068
9069 /*
9070  * mono_class_get_virtual_methods:
9071  *
9072  *   Iterate over the virtual methods of KLASS.
9073  *
9074  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9075  */
9076 static MonoMethod*
9077 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9078 {
9079         MonoMethod** method;
9080         if (!iter)
9081                 return NULL;
9082         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9083                 if (!*iter) {
9084                         mono_class_setup_methods (klass);
9085                         /*
9086                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9087                          * FIXME we should better report this error to the caller
9088                          */
9089                         if (!klass->methods)
9090                                 return NULL;
9091                         /* start from the first */
9092                         method = &klass->methods [0];
9093                 } else {
9094                         method = (MonoMethod **)*iter;
9095                         method++;
9096                 }
9097                 int mcount = mono_class_get_method_count (klass);
9098                 while (method < &klass->methods [mcount]) {
9099                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9100                                 break;
9101                         method ++;
9102                 }
9103                 if (method < &klass->methods [mcount]) {
9104                         *iter = method;
9105                         return *method;
9106                 } else {
9107                         return NULL;
9108                 }
9109         } else {
9110                 /* Search directly in metadata to avoid calling setup_methods () */
9111                 MonoMethod *res = NULL;
9112                 int i, start_index;
9113
9114                 if (!*iter) {
9115                         start_index = 0;
9116                 } else {
9117                         start_index = GPOINTER_TO_UINT (*iter);
9118                 }
9119
9120                 int first_idx = mono_class_get_first_method_idx (klass);
9121                 int mcount = mono_class_get_method_count (klass);
9122                 for (i = start_index; i < mcount; ++i) {
9123                         guint32 flags;
9124
9125                         /* first_idx points into the methodptr table */
9126                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, first_idx + i, MONO_METHOD_FLAGS);
9127
9128                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9129                                 break;
9130                 }
9131
9132                 if (i < mcount) {
9133                         MonoError error;
9134                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9135                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9136
9137                         /* Add 1 here so the if (*iter) check fails */
9138                         *iter = GUINT_TO_POINTER (i + 1);
9139                         return res;
9140                 } else {
9141                         return NULL;
9142                 }
9143         }
9144 }
9145
9146 /**
9147  * mono_class_get_properties:
9148  * @klass: the MonoClass to act on
9149  *
9150  * This routine is an iterator routine for retrieving the properties in a class.
9151  *
9152  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9153  * iterate over all of the elements.  When no more values are
9154  * available, the return value is NULL.
9155  *
9156  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9157  */
9158 MonoProperty*
9159 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9160 {
9161         MonoProperty* property;
9162         if (!iter)
9163                 return NULL;
9164         if (!*iter) {
9165                 mono_class_setup_properties (klass);
9166                 MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9167                 /* start from the first */
9168                 if (info->count) {
9169                         *iter = &info->properties [0];
9170                         return (MonoProperty *)*iter;
9171                 } else {
9172                         /* no fields */
9173                         return NULL;
9174                 }
9175         }
9176         property = (MonoProperty *)*iter;
9177         property++;
9178         MonoClassPropertyInfo *info = mono_class_get_property_info (klass);
9179         if (property < &info->properties [info->count]) {
9180                 *iter = property;
9181                 return (MonoProperty *)*iter;
9182         }
9183         return NULL;
9184 }
9185
9186 /**
9187  * mono_class_get_events:
9188  * @klass: the MonoClass to act on
9189  *
9190  * This routine is an iterator routine for retrieving the properties in a class.
9191  *
9192  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9193  * iterate over all of the elements.  When no more values are
9194  * available, the return value is NULL.
9195  *
9196  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9197  */
9198 MonoEvent*
9199 mono_class_get_events (MonoClass* klass, gpointer *iter)
9200 {
9201         MonoEvent* event;
9202         if (!iter)
9203                 return NULL;
9204         if (!*iter) {
9205                 mono_class_setup_events (klass);
9206                 MonoClassEventInfo *info = mono_class_get_event_info (klass);
9207                 /* start from the first */
9208                 if (info->count) {
9209                         *iter = &info->events [0];
9210                         return (MonoEvent *)*iter;
9211                 } else {
9212                         /* no fields */
9213                         return NULL;
9214                 }
9215         }
9216         event = (MonoEvent *)*iter;
9217         event++;
9218         MonoClassEventInfo *info = mono_class_get_event_info (klass);
9219         if (event < &info->events [info->count]) {
9220                 *iter = event;
9221                 return (MonoEvent *)*iter;
9222         }
9223         return NULL;
9224 }
9225
9226 /**
9227  * mono_class_get_interfaces
9228  * @klass: the MonoClass to act on
9229  *
9230  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9231  *
9232  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9233  * iterate over all of the elements.  When no more values are
9234  * available, the return value is NULL.
9235  *
9236  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9237  */
9238 MonoClass*
9239 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9240 {
9241         MonoError error;
9242         MonoClass** iface;
9243         if (!iter)
9244                 return NULL;
9245         if (!*iter) {
9246                 if (!klass->inited)
9247                         mono_class_init (klass);
9248                 if (!klass->interfaces_inited) {
9249                         mono_class_setup_interfaces (klass, &error);
9250                         if (!mono_error_ok (&error)) {
9251                                 mono_error_cleanup (&error);
9252                                 return NULL;
9253                         }
9254                 }
9255                 /* start from the first */
9256                 if (klass->interface_count) {
9257                         *iter = &klass->interfaces [0];
9258                         return klass->interfaces [0];
9259                 } else {
9260                         /* no interface */
9261                         return NULL;
9262                 }
9263         }
9264         iface = (MonoClass **)*iter;
9265         iface++;
9266         if (iface < &klass->interfaces [klass->interface_count]) {
9267                 *iter = iface;
9268                 return *iface;
9269         }
9270         return NULL;
9271 }
9272
9273 static void
9274 setup_nested_types (MonoClass *klass)
9275 {
9276         MonoError error;
9277         GList *classes, *nested_classes, *l;
9278         int i;
9279
9280         if (klass->nested_classes_inited)
9281                 return;
9282
9283         if (!klass->type_token)
9284                 klass->nested_classes_inited = TRUE;
9285
9286         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9287         classes = NULL;
9288         while (i) {
9289                 MonoClass* nclass;
9290                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9291                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9292                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9293                 if (!mono_error_ok (&error)) {
9294                         /*FIXME don't swallow the error message*/
9295                         mono_error_cleanup (&error);
9296
9297                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9298                         continue;
9299                 }
9300
9301                 classes = g_list_prepend (classes, nclass);
9302
9303                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9304         }
9305
9306         nested_classes = NULL;
9307         for (l = classes; l; l = l->next)
9308                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9309         g_list_free (classes);
9310
9311         mono_loader_lock ();
9312         if (!klass->nested_classes_inited) {
9313                 mono_class_set_nested_classes_property (klass, nested_classes);
9314                 mono_memory_barrier ();
9315                 klass->nested_classes_inited = TRUE;
9316         }
9317         mono_loader_unlock ();
9318 }
9319
9320 /**
9321  * mono_class_get_nested_types
9322  * @klass: the MonoClass to act on
9323  *
9324  * This routine is an iterator routine for retrieving the nested types of a class.
9325  * This works only if @klass is non-generic, or a generic type definition.
9326  *
9327  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9328  * iterate over all of the elements.  When no more values are
9329  * available, the return value is NULL.
9330  *
9331  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9332  */
9333 MonoClass*
9334 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9335 {
9336         GList *item;
9337
9338         if (!iter)
9339                 return NULL;
9340         if (!klass->nested_classes_inited)
9341                 setup_nested_types (klass);
9342
9343         if (!*iter) {
9344                 GList *nested_classes = mono_class_get_nested_classes_property (klass);
9345                 /* start from the first */
9346                 if (nested_classes) {
9347                         *iter = nested_classes;
9348                         return (MonoClass *)nested_classes->data;
9349                 } else {
9350                         /* no nested types */
9351                         return NULL;
9352                 }
9353         }
9354         item = (GList *)*iter;
9355         item = item->next;
9356         if (item) {
9357                 *iter = item;
9358                 return (MonoClass *)item->data;
9359         }
9360         return NULL;
9361 }
9362
9363
9364 /**
9365  * mono_class_is_delegate
9366  * @klass: the MonoClass to act on
9367  *
9368  * Returns: TRUE if the MonoClass represents a System.Delegate.
9369  */
9370 mono_bool
9371 mono_class_is_delegate (MonoClass *klass)
9372 {
9373         return klass->delegate;
9374 }
9375
9376 /**
9377  * mono_class_implements_interface
9378  * @klass: The MonoClass to act on
9379  * @interface: The interface to check if @klass implements.
9380  *
9381  * Returns: TRUE if @klass implements @interface.
9382  */
9383 mono_bool
9384 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9385 {
9386         return mono_class_is_assignable_from (iface, klass);
9387 }
9388
9389 /**
9390  * mono_field_get_name:
9391  * @field: the MonoClassField to act on
9392  *
9393  * Returns: The name of the field.
9394  */
9395 const char*
9396 mono_field_get_name (MonoClassField *field)
9397 {
9398         return field->name;
9399 }
9400
9401 /**
9402  * mono_field_get_type:
9403  * @field: the MonoClassField to act on
9404  *
9405  * Returns: MonoType of the field.
9406  */
9407 MonoType*
9408 mono_field_get_type (MonoClassField *field)
9409 {
9410         MonoError error;
9411         MonoType *type = mono_field_get_type_checked (field, &error);
9412         if (!mono_error_ok (&error)) {
9413                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9414                 mono_error_cleanup (&error);
9415         }
9416         return type;
9417 }
9418
9419
9420 /**
9421  * mono_field_get_type_checked:
9422  * @field: the MonoClassField to act on
9423  * @error: used to return any erro found while retrieving @field type
9424  *
9425  * Returns: MonoType of the field.
9426  */
9427 MonoType*
9428 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9429 {
9430         mono_error_init (error);
9431         if (!field->type)
9432                 mono_field_resolve_type (field, error);
9433         return field->type;
9434 }
9435
9436 /**
9437  * mono_field_get_parent:
9438  * @field: the MonoClassField to act on
9439  *
9440  * Returns: MonoClass where the field was defined.
9441  */
9442 MonoClass*
9443 mono_field_get_parent (MonoClassField *field)
9444 {
9445         return field->parent;
9446 }
9447
9448 /**
9449  * mono_field_get_flags;
9450  * @field: the MonoClassField to act on
9451  *
9452  * The metadata flags for a field are encoded using the
9453  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9454  *
9455  * Returns: The flags for the field.
9456  */
9457 guint32
9458 mono_field_get_flags (MonoClassField *field)
9459 {
9460         if (!field->type)
9461                 return mono_field_resolve_flags (field);
9462         return field->type->attrs;
9463 }
9464
9465 /**
9466  * mono_field_get_offset:
9467  * @field: the MonoClassField to act on
9468  *
9469  * Returns: The field offset.
9470  */
9471 guint32
9472 mono_field_get_offset (MonoClassField *field)
9473 {
9474         return field->offset;
9475 }
9476
9477 static const char *
9478 mono_field_get_rva (MonoClassField *field)
9479 {
9480         guint32 rva;
9481         int field_index;
9482         MonoClass *klass = field->parent;
9483         MonoFieldDefaultValue *def_values;
9484
9485         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9486
9487         def_values = mono_class_get_field_def_values (klass);
9488         if (!def_values) {
9489                 def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * mono_class_get_field_count (klass));
9490
9491                 mono_class_set_field_def_values (klass, def_values);
9492         }
9493
9494         field_index = mono_field_get_index (field);
9495                 
9496         if (!def_values [field_index].data && !image_is_dynamic (klass->image)) {
9497                 int first_field_idx = mono_class_get_first_field_idx (klass);
9498                 mono_metadata_field_info (field->parent->image, first_field_idx + field_index, NULL, &rva, NULL);
9499                 if (!rva)
9500                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9501                 def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9502         }
9503
9504         return def_values [field_index].data;
9505 }
9506
9507 /**
9508  * mono_field_get_data:
9509  * @field: the MonoClassField to act on
9510  *
9511  * Returns: A pointer to the metadata constant value or to the field
9512  * data if it has an RVA flag.
9513  */
9514 const char *
9515 mono_field_get_data (MonoClassField *field)
9516 {
9517         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9518                 MonoTypeEnum def_type;
9519
9520                 return mono_class_get_field_default_value (field, &def_type);
9521         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9522                 return mono_field_get_rva (field);
9523         } else {
9524                 return NULL;
9525         }
9526 }
9527
9528 /**
9529  * mono_property_get_name: 
9530  * @prop: the MonoProperty to act on
9531  *
9532  * Returns: The name of the property
9533  */
9534 const char*
9535 mono_property_get_name (MonoProperty *prop)
9536 {
9537         return prop->name;
9538 }
9539
9540 /**
9541  * mono_property_get_set_method
9542  * @prop: the MonoProperty to act on.
9543  *
9544  * Returns: The setter method of the property (A MonoMethod)
9545  */
9546 MonoMethod*
9547 mono_property_get_set_method (MonoProperty *prop)
9548 {
9549         return prop->set;
9550 }
9551
9552 /**
9553  * mono_property_get_get_method
9554  * @prop: the MonoProperty to act on.
9555  *
9556  * Returns: The setter method of the property (A MonoMethod)
9557  */
9558 MonoMethod*
9559 mono_property_get_get_method (MonoProperty *prop)
9560 {
9561         return prop->get;
9562 }
9563
9564 /**
9565  * mono_property_get_parent:
9566  * @prop: the MonoProperty to act on.
9567  *
9568  * Returns: The MonoClass where the property was defined.
9569  */
9570 MonoClass*
9571 mono_property_get_parent (MonoProperty *prop)
9572 {
9573         return prop->parent;
9574 }
9575
9576 /**
9577  * mono_property_get_flags:
9578  * @prop: the MonoProperty to act on.
9579  *
9580  * The metadata flags for a property are encoded using the
9581  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9582  *
9583  * Returns: The flags for the property.
9584  */
9585 guint32
9586 mono_property_get_flags (MonoProperty *prop)
9587 {
9588         return prop->attrs;
9589 }
9590
9591 /**
9592  * mono_event_get_name:
9593  * @event: the MonoEvent to act on
9594  *
9595  * Returns: The name of the event.
9596  */
9597 const char*
9598 mono_event_get_name (MonoEvent *event)
9599 {
9600         return event->name;
9601 }
9602
9603 /**
9604  * mono_event_get_add_method:
9605  * @event: The MonoEvent to act on.
9606  *
9607  * Returns: The @add' method for the event (a MonoMethod).
9608  */
9609 MonoMethod*
9610 mono_event_get_add_method (MonoEvent *event)
9611 {
9612         return event->add;
9613 }
9614
9615 /**
9616  * mono_event_get_remove_method:
9617  * @event: The MonoEvent to act on.
9618  *
9619  * Returns: The @remove method for the event (a MonoMethod).
9620  */
9621 MonoMethod*
9622 mono_event_get_remove_method (MonoEvent *event)
9623 {
9624         return event->remove;
9625 }
9626
9627 /**
9628  * mono_event_get_raise_method:
9629  * @event: The MonoEvent to act on.
9630  *
9631  * Returns: The @raise method for the event (a MonoMethod).
9632  */
9633 MonoMethod*
9634 mono_event_get_raise_method (MonoEvent *event)
9635 {
9636         return event->raise;
9637 }
9638
9639 /**
9640  * mono_event_get_parent:
9641  * @event: the MonoEvent to act on.
9642  *
9643  * Returns: The MonoClass where the event is defined.
9644  */
9645 MonoClass*
9646 mono_event_get_parent (MonoEvent *event)
9647 {
9648         return event->parent;
9649 }
9650
9651 /**
9652  * mono_event_get_flags
9653  * @event: the MonoEvent to act on.
9654  *
9655  * The metadata flags for an event are encoded using the
9656  * EVENT_* constants.  See the tabledefs.h file for details.
9657  *
9658  * Returns: The flags for the event.
9659  */
9660 guint32
9661 mono_event_get_flags (MonoEvent *event)
9662 {
9663         return event->attrs;
9664 }
9665
9666 /**
9667  * mono_class_get_method_from_name:
9668  * @klass: where to look for the method
9669  * @name: name of the method
9670  * @param_count: number of parameters. -1 for any number.
9671  *
9672  * Obtains a MonoMethod with a given name and number of parameters.
9673  * It only works if there are no multiple signatures for any given method name.
9674  */
9675 MonoMethod *
9676 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9677 {
9678         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9679 }
9680
9681 static MonoMethod*
9682 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9683 {
9684         MonoMethod *res = NULL;
9685         int i;
9686
9687         /* Search directly in the metadata to avoid calling setup_methods () */
9688         int first_idx = mono_class_get_first_method_idx (klass);
9689         int mcount = mono_class_get_method_count (klass);
9690         for (i = 0; i < mcount; ++i) {
9691                 MonoError error;
9692                 guint32 cols [MONO_METHOD_SIZE];
9693                 MonoMethod *method;
9694                 MonoMethodSignature *sig;
9695
9696                 /* first_idx points into the methodptr table */
9697                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, first_idx + i, cols, MONO_METHOD_SIZE);
9698
9699                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9700                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (first_idx + i + 1), klass, NULL, &error);
9701                         if (!method) {
9702                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9703                                 continue;
9704                         }
9705                         if (param_count == -1) {
9706                                 res = method;
9707                                 break;
9708                         }
9709                         sig = mono_method_signature_checked (method, &error);
9710                         if (!sig) {
9711                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9712                                 continue;
9713                         }
9714                         if (sig->param_count == param_count) {
9715                                 res = method;
9716                                 break;
9717                         }
9718                 }
9719         }
9720
9721         return res;
9722 }
9723
9724 /**
9725  * mono_class_get_method_from_name_flags:
9726  * @klass: where to look for the method
9727  * @name_space: name of the method
9728  * @param_count: number of parameters. -1 for any number.
9729  * @flags: flags which must be set in the method
9730  *
9731  * Obtains a MonoMethod with a given name and number of parameters.
9732  * It only works if there are no multiple signatures for any given method name.
9733  */
9734 MonoMethod *
9735 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9736 {
9737         MonoMethod *res = NULL;
9738         int i;
9739
9740         mono_class_init (klass);
9741
9742         if (mono_class_is_ginst (klass) && !klass->methods) {
9743                 res = mono_class_get_method_from_name_flags (mono_class_get_generic_class (klass)->container_class, name, param_count, flags);
9744                 if (res) {
9745                         MonoError error;
9746                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9747                         if (!mono_error_ok (&error))
9748                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9749                 }
9750                 return res;
9751         }
9752
9753         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9754                 mono_class_setup_methods (klass);
9755                 /*
9756                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9757                 See mono/tests/array_load_exception.il
9758                 FIXME we should better report this error to the caller
9759                  */
9760                 if (!klass->methods)
9761                         return NULL;
9762                 int mcount = mono_class_get_method_count (klass);
9763                 for (i = 0; i < mcount; ++i) {
9764                         MonoMethod *method = klass->methods [i];
9765
9766                         if (method->name[0] == name [0] && 
9767                                 !strcmp (name, method->name) &&
9768                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9769                                 ((method->flags & flags) == flags)) {
9770                                 res = method;
9771                                 break;
9772                         }
9773                 }
9774         }
9775         else {
9776             res = find_method_in_metadata (klass, name, param_count, flags);
9777         }
9778
9779         return res;
9780 }
9781
9782 /**
9783  * mono_class_set_failure:
9784  * @klass: class in which the failure was detected
9785  * @ex_type: the kind of exception/error to be thrown (later)
9786  * @ex_data: exception data (specific to each type of exception/error)
9787  *
9788  * Keep a detected failure informations in the class for later processing.
9789  * Note that only the first failure is kept.
9790  *
9791  * LOCKING: Acquires the loader lock.
9792  */
9793 static gboolean
9794 mono_class_set_failure (MonoClass *klass, MonoErrorBoxed *boxed_error)
9795 {
9796         g_assert (boxed_error != NULL);
9797
9798         if (mono_class_has_failure (klass))
9799                 return FALSE;
9800
9801         mono_loader_lock ();
9802         klass->has_failure = 1;
9803         mono_class_set_exception_data (klass, boxed_error);
9804         mono_loader_unlock ();
9805
9806         return TRUE;
9807 }
9808
9809 gboolean
9810 mono_class_has_failure (const MonoClass *klass)
9811 {
9812         g_assert (klass != NULL);
9813         return klass->has_failure != 0;
9814 }
9815
9816
9817 /**
9818  * mono_class_set_type_load_failure:
9819  * @klass: class in which the failure was detected
9820  * @fmt: Printf-style error message string.
9821  *
9822  * Collect detected failure informaion in the class for later processing.
9823  * The error is stored as a MonoErrorBoxed as with mono_error_set_type_load_class ()
9824  * Note that only the first failure is kept.
9825  *
9826  * Returns FALSE if a failure was already set on the class, or TRUE otherwise.
9827  *
9828  * LOCKING: Acquires the loader lock.
9829  */
9830 gboolean
9831 mono_class_set_type_load_failure (MonoClass *klass, const char * fmt, ...)
9832 {
9833         MonoError prepare_error;
9834         va_list args;
9835
9836         if (mono_class_has_failure (klass))
9837                 return FALSE;
9838         
9839         mono_error_init (&prepare_error);
9840         
9841         va_start (args, fmt);
9842         mono_error_vset_type_load_class (&prepare_error, klass, fmt, args);
9843         va_end (args);
9844
9845         MonoErrorBoxed *box = mono_error_box (&prepare_error, klass->image);
9846         mono_error_cleanup (&prepare_error);
9847         return mono_class_set_failure (klass, box);
9848 }
9849
9850 /**
9851  * mono_classes_init:
9852  *
9853  * Initialize the resources used by this module.
9854  */
9855 void
9856 mono_classes_init (void)
9857 {
9858         mono_os_mutex_init (&classes_mutex);
9859
9860         mono_native_tls_alloc (&setup_fields_tls_id, NULL);
9861         mono_native_tls_alloc (&init_pending_tls_id, NULL);
9862
9863         mono_counters_register ("MonoClassDef count",
9864                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_def_count);
9865         mono_counters_register ("MonoClassGtd count",
9866                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gtd_count);
9867         mono_counters_register ("MonoClassGenericInst count",
9868                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ginst_count);
9869         mono_counters_register ("MonoClassGenericParam count",
9870                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_gparam_count);
9871         mono_counters_register ("MonoClassArray count",
9872                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_array_count);
9873         mono_counters_register ("MonoClassPointer count",
9874                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_pointer_count);
9875         mono_counters_register ("Inflated methods size",
9876                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
9877         mono_counters_register ("Inflated classes size",
9878                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
9879         mono_counters_register ("MonoClass size",
9880                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
9881 }
9882
9883 /**
9884  * mono_classes_cleanup:
9885  *
9886  * Free the resources used by this module.
9887  */
9888 void
9889 mono_classes_cleanup (void)
9890 {
9891         mono_native_tls_free (setup_fields_tls_id);
9892         mono_native_tls_free (init_pending_tls_id);
9893
9894         if (global_interface_bitset)
9895                 mono_bitset_free (global_interface_bitset);
9896         global_interface_bitset = NULL;
9897         mono_os_mutex_destroy (&classes_mutex);
9898 }
9899
9900 /**
9901  * mono_class_get_exception_for_failure:
9902  * @klass: class in which the failure was detected
9903  *
9904  * Return a constructed MonoException than the caller can then throw
9905  * using mono_raise_exception - or NULL if no failure is present (or
9906  * doesn't result in an exception).
9907  */
9908 MonoException*
9909 mono_class_get_exception_for_failure (MonoClass *klass)
9910 {
9911         if (!mono_class_has_failure (klass))
9912                 return NULL;
9913         MonoError unboxed_error;
9914         mono_error_init (&unboxed_error);
9915         mono_error_set_for_class_failure (&unboxed_error, klass);
9916         return mono_error_convert_to_exception (&unboxed_error);
9917 }
9918
9919 static gboolean
9920 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
9921  {
9922         outer_klass = mono_class_get_generic_type_definition (outer_klass);
9923         inner_klass = mono_class_get_generic_type_definition (inner_klass);
9924         do {
9925                 if (outer_klass == inner_klass)
9926                         return TRUE;
9927                 inner_klass = inner_klass->nested_in;
9928         } while (inner_klass);
9929         return FALSE;
9930 }
9931
9932 MonoClass *
9933 mono_class_get_generic_type_definition (MonoClass *klass)
9934 {
9935         MonoGenericClass *gklass =  mono_class_try_get_generic_class (klass);
9936         return gklass ? gklass->container_class : klass;
9937 }
9938
9939 /*
9940  * Check if @klass is a subtype of @parent ignoring generic instantiations.
9941  * 
9942  * Generic instantiations are ignored for all super types of @klass.
9943  * 
9944  * Visibility checks ignoring generic instantiations.  
9945  */
9946 gboolean
9947 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
9948 {
9949         int i;
9950         klass = mono_class_get_generic_type_definition (klass);
9951         parent = mono_class_get_generic_type_definition (parent);
9952         mono_class_setup_supertypes (klass);
9953
9954         for (i = 0; i < klass->idepth; ++i) {
9955                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
9956                         return TRUE;
9957         }
9958         return FALSE;
9959 }
9960 /*
9961  * Subtype can only access parent members with family protection if the site object
9962  * is subclass of Subtype. For example:
9963  * class A { protected int x; }
9964  * class B : A {
9965  *      void valid_access () {
9966  *              B b;
9967  *              b.x = 0;
9968  *  }
9969  *  void invalid_access () {
9970  *              A a;
9971  *              a.x = 0;
9972  *  }
9973  * }
9974  * */
9975 static gboolean
9976 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
9977 {
9978         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
9979                 return FALSE;
9980
9981         if (context_klass == NULL)
9982                 return TRUE;
9983         /*if access_klass is not member_klass context_klass must be type compat*/
9984         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
9985                 return FALSE;
9986         return TRUE;
9987 }
9988
9989 static gboolean
9990 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
9991 {
9992         GSList *tmp;
9993         if (accessing == accessed)
9994                 return TRUE;
9995         if (!accessed || !accessing)
9996                 return FALSE;
9997
9998         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
9999          * anywhere so untrusted friends are not safe to access platform's code internals */
10000         if (mono_security_core_clr_enabled ()) {
10001                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10002                         return FALSE;
10003         }
10004
10005         mono_assembly_load_friends (accessed);
10006         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10007                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10008                 /* Be conservative with checks */
10009                 if (!friend_->name)
10010                         continue;
10011                 if (strcmp (accessing->aname.name, friend_->name))
10012                         continue;
10013                 if (friend_->public_key_token [0]) {
10014                         if (!accessing->aname.public_key_token [0])
10015                                 continue;
10016                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10017                                 continue;
10018                 }
10019                 return TRUE;
10020         }
10021         return FALSE;
10022 }
10023
10024 /*
10025  * If klass is a generic type or if it is derived from a generic type, return the
10026  * MonoClass of the generic definition
10027  * Returns NULL if not found
10028  */
10029 static MonoClass*
10030 get_generic_definition_class (MonoClass *klass)
10031 {
10032         while (klass) {
10033                 MonoGenericClass *gklass = mono_class_try_get_generic_class (klass);
10034                 if (gklass && gklass->container_class)
10035                         return gklass->container_class;
10036                 klass = klass->parent;
10037         }
10038         return NULL;
10039 }
10040
10041 static gboolean
10042 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10043 {
10044         int i;
10045         for (i = 0; i < ginst->type_argc; ++i) {
10046                 MonoType *type = ginst->type_argv[i];
10047                 switch (type->type) {
10048                 case MONO_TYPE_SZARRAY:
10049                         if (!can_access_type (access_klass, type->data.klass))
10050                                 return FALSE;
10051                         break;
10052                 case MONO_TYPE_ARRAY:
10053                         if (!can_access_type (access_klass, type->data.array->eklass))
10054                                 return FALSE;
10055                         break;
10056                 case MONO_TYPE_PTR:
10057                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10058                                 return FALSE;
10059                         break;
10060                 case MONO_TYPE_CLASS:
10061                 case MONO_TYPE_VALUETYPE:
10062                 case MONO_TYPE_GENERICINST:
10063                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10064                                 return FALSE;
10065                 default:
10066                         break;
10067                 }
10068         }
10069         return TRUE;
10070 }
10071
10072 static gboolean
10073 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10074 {
10075         int access_level;
10076
10077         if (access_klass == member_klass)
10078                 return TRUE;
10079
10080         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10081                 return TRUE;
10082
10083         if (access_klass->element_class && !access_klass->enumtype)
10084                 access_klass = access_klass->element_class;
10085
10086         if (member_klass->element_class && !member_klass->enumtype)
10087                 member_klass = member_klass->element_class;
10088
10089         access_level = mono_class_get_flags (member_klass) & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10090
10091         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10092                 return TRUE;
10093
10094         if (mono_class_is_ginst (member_klass) && !can_access_instantiation (access_klass, mono_class_get_generic_class (member_klass)->context.class_inst))
10095                 return FALSE;
10096
10097         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10098                 return TRUE;
10099
10100         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10101                 return FALSE;
10102
10103         /*Non nested type with nested visibility. We just fail it.*/
10104         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10105                 return FALSE;
10106
10107         switch (access_level) {
10108         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10109                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10110
10111         case TYPE_ATTRIBUTE_PUBLIC:
10112                 return TRUE;
10113
10114         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10115                 return TRUE;
10116
10117         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10118                 return is_nesting_type (member_klass, access_klass);
10119
10120         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10121                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10122
10123         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10124                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10125
10126         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10127                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10128                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10129
10130         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10131                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10132                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10133         }
10134         return FALSE;
10135 }
10136
10137 /* FIXME: check visibility of type, too */
10138 static gboolean
10139 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10140 {
10141         MonoClass *member_generic_def;
10142         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10143                 return TRUE;
10144
10145         MonoGenericClass *access_gklass = mono_class_try_get_generic_class (access_klass);
10146         if (((access_gklass && access_gklass->container_class) ||
10147                                         mono_class_is_gtd (access_klass)) && 
10148                         (member_generic_def = get_generic_definition_class (member_klass))) {
10149                 MonoClass *access_container;
10150
10151                 if (mono_class_is_gtd (access_klass))
10152                         access_container = access_klass;
10153                 else
10154                         access_container = access_gklass->container_class;
10155
10156                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10157                         return TRUE;
10158         }
10159
10160         /* Partition I 8.5.3.2 */
10161         /* the access level values are the same for fields and methods */
10162         switch (access_level) {
10163         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10164                 /* same compilation unit */
10165                 return access_klass->image == member_klass->image;
10166         case FIELD_ATTRIBUTE_PRIVATE:
10167                 return access_klass == member_klass;
10168         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10169                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10170                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10171                         return TRUE;
10172                 return FALSE;
10173         case FIELD_ATTRIBUTE_ASSEMBLY:
10174                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10175         case FIELD_ATTRIBUTE_FAMILY:
10176                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10177                         return TRUE;
10178                 return FALSE;
10179         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10180                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10181                         return TRUE;
10182                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10183         case FIELD_ATTRIBUTE_PUBLIC:
10184                 return TRUE;
10185         }
10186         return FALSE;
10187 }
10188
10189 /**
10190  * mono_method_can_access_field:
10191  * @method: Method that will attempt to access the field
10192  * @field: the field to access
10193  *
10194  * Used to determine if a method is allowed to access the specified field.
10195  *
10196  * Returns: TRUE if the given @method is allowed to access the @field while following
10197  * the accessibility rules of the CLI.
10198  */
10199 gboolean
10200 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10201 {
10202         /* FIXME: check all overlapping fields */
10203         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10204         if (!can) {
10205                 MonoClass *nested = method->klass->nested_in;
10206                 while (nested) {
10207                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10208                         if (can)
10209                                 return TRUE;
10210                         nested = nested->nested_in;
10211                 }
10212         }
10213         return can;
10214 }
10215
10216 /**
10217  * mono_method_can_access_method:
10218  * @method: Method that will attempt to access the other method
10219  * @called: the method that we want to probe for accessibility.
10220  *
10221  * Used to determine if the @method is allowed to access the specified @called method.
10222  *
10223  * Returns: TRUE if the given @method is allowed to invoke the @called while following
10224  * the accessibility rules of the CLI.
10225  */
10226 gboolean
10227 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10228 {
10229         method = mono_method_get_method_definition (method);
10230         called = mono_method_get_method_definition (called);
10231         return mono_method_can_access_method_full (method, called, NULL);
10232 }
10233
10234 /*
10235  * mono_method_can_access_method_full:
10236  * @method: The caller method 
10237  * @called: The called method 
10238  * @context_klass: The static type on stack of the owner @called object used
10239  * 
10240  * This function must be used with instance calls, as they have more strict family accessibility.
10241  * It can be used with static methods, but context_klass should be NULL.
10242  * 
10243  * Returns: TRUE if caller have proper visibility and acessibility to @called
10244  */
10245 gboolean
10246 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10247 {
10248         /* Wrappers are except from access checks */
10249         if (method->wrapper_type != MONO_WRAPPER_NONE || called->wrapper_type != MONO_WRAPPER_NONE)
10250                 return TRUE;
10251
10252         MonoClass *access_class = method->klass;
10253         MonoClass *member_class = called->klass;
10254         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10255         if (!can) {
10256                 MonoClass *nested = access_class->nested_in;
10257                 while (nested) {
10258                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10259                         if (can)
10260                                 break;
10261                         nested = nested->nested_in;
10262                 }
10263         }
10264
10265         if (!can)
10266                 return FALSE;
10267
10268         can = can_access_type (access_class, member_class);
10269         if (!can) {
10270                 MonoClass *nested = access_class->nested_in;
10271                 while (nested) {
10272                         can = can_access_type (nested, member_class);
10273                         if (can)
10274                                 break;
10275                         nested = nested->nested_in;
10276                 }
10277         }
10278
10279         if (!can)
10280                 return FALSE;
10281
10282         if (called->is_inflated) {
10283                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10284                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10285                         return FALSE;
10286         }
10287                 
10288         return TRUE;
10289 }
10290
10291
10292 /*
10293  * mono_method_can_access_field_full:
10294  * @method: The caller method 
10295  * @field: The accessed field
10296  * @context_klass: The static type on stack of the owner @field object used
10297  * 
10298  * This function must be used with instance fields, as they have more strict family accessibility.
10299  * It can be used with static fields, but context_klass should be NULL.
10300  * 
10301  * Returns: TRUE if caller have proper visibility and acessibility to @field
10302  */
10303 gboolean
10304 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10305 {
10306         MonoClass *access_class = method->klass;
10307         MonoClass *member_class = field->parent;
10308         /* FIXME: check all overlapping fields */
10309         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10310         if (!can) {
10311                 MonoClass *nested = access_class->nested_in;
10312                 while (nested) {
10313                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10314                         if (can)
10315                                 break;
10316                         nested = nested->nested_in;
10317                 }
10318         }
10319
10320         if (!can)
10321                 return FALSE;
10322
10323         can = can_access_type (access_class, member_class);
10324         if (!can) {
10325                 MonoClass *nested = access_class->nested_in;
10326                 while (nested) {
10327                         can = can_access_type (nested, member_class);
10328                         if (can)
10329                                 break;
10330                         nested = nested->nested_in;
10331                 }
10332         }
10333
10334         if (!can)
10335                 return FALSE;
10336         return TRUE;
10337 }
10338
10339 /*
10340  * mono_class_can_access_class:
10341  * @source_class: The source class 
10342  * @target_class: The accessed class
10343  * 
10344  * This function returns is @target_class is visible to @source_class
10345  * 
10346  * Returns: TRUE if source have proper visibility and acessibility to target
10347  */
10348 gboolean
10349 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10350 {
10351         return can_access_type (source_class, target_class);
10352 }
10353
10354 /**
10355  * mono_type_is_valid_enum_basetype:
10356  * @type: The MonoType to check
10357  *
10358  * Returns: TRUE if the type can be used as the basetype of an enum
10359  */
10360 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10361         switch (type->type) {
10362         case MONO_TYPE_I1:
10363         case MONO_TYPE_U1:
10364         case MONO_TYPE_BOOLEAN:
10365         case MONO_TYPE_I2:
10366         case MONO_TYPE_U2:
10367         case MONO_TYPE_CHAR:
10368         case MONO_TYPE_I4:
10369         case MONO_TYPE_U4:
10370         case MONO_TYPE_I8:
10371         case MONO_TYPE_U8:
10372         case MONO_TYPE_I:
10373         case MONO_TYPE_U:
10374                 return TRUE;
10375         default:
10376                 return FALSE;
10377         }
10378 }
10379
10380 /**
10381  * mono_class_is_valid_enum:
10382  * @klass: An enum class to be validated
10383  *
10384  * This method verify the required properties an enum should have.
10385  *  
10386  * Returns: TRUE if the informed enum class is valid 
10387  *
10388  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10389  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10390  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10391  */
10392 gboolean
10393 mono_class_is_valid_enum (MonoClass *klass)
10394 {
10395         MonoClassField * field;
10396         gpointer iter = NULL;
10397         gboolean found_base_field = FALSE;
10398
10399         g_assert (klass->enumtype);
10400         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10401         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10402                 return FALSE;
10403         }
10404
10405         if (!mono_class_is_auto_layout (klass))
10406                 return FALSE;
10407
10408         while ((field = mono_class_get_fields (klass, &iter))) {
10409                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10410                         if (found_base_field)
10411                                 return FALSE;
10412                         found_base_field = TRUE;
10413                         if (!mono_type_is_valid_enum_basetype (field->type))
10414                                 return FALSE;
10415                 }
10416         }
10417
10418         if (!found_base_field)
10419                 return FALSE;
10420
10421         if (mono_class_get_method_count (klass) > 0)
10422                 return FALSE;
10423
10424         return TRUE;
10425 }
10426
10427 gboolean
10428 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10429 {
10430         return gklass->context.class_inst == mono_class_get_generic_container (gklass->container_class)->context.class_inst;
10431 }
10432
10433 /*
10434  * mono_class_setup_interface_id:
10435  *
10436  * Initializes MonoClass::interface_id if required.
10437  *
10438  * LOCKING: Acquires the loader lock.
10439  */
10440 void
10441 mono_class_setup_interface_id (MonoClass *klass)
10442 {
10443         mono_loader_lock ();
10444         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10445                 klass->interface_id = mono_get_unique_iid (klass);
10446         mono_loader_unlock ();
10447 }
10448
10449 /*
10450  * mono_class_setup_interfaces:
10451  *
10452  *   Initialize klass->interfaces/interfaces_count.
10453  * LOCKING: Acquires the loader lock.
10454  * This function can fail the type.
10455  */
10456 void
10457 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10458 {
10459         int i, interface_count;
10460         MonoClass **interfaces;
10461
10462         mono_error_init (error);
10463
10464         if (klass->interfaces_inited)
10465                 return;
10466
10467         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10468                 MonoType *args [1];
10469
10470                 /* generic IList, ICollection, IEnumerable */
10471                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10472                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10473
10474                 args [0] = &klass->element_class->byval_arg;
10475                 interfaces [0] = mono_class_bind_generic_parameters (
10476                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10477                 if (interface_count > 1)
10478                         interfaces [1] = mono_class_bind_generic_parameters (
10479                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10480         } else if (mono_class_is_ginst (klass)) {
10481                 MonoClass *gklass = mono_class_get_generic_class (klass)->container_class;
10482
10483                 mono_class_setup_interfaces (gklass, error);
10484                 if (!mono_error_ok (error)) {
10485                         mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10486                         return;
10487                 }
10488
10489                 interface_count = gklass->interface_count;
10490                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10491                 for (i = 0; i < interface_count; i++) {
10492                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (mono_class_get_generic_class (klass)), error);
10493                         if (!mono_error_ok (error)) {
10494                                 mono_class_set_type_load_failure (klass, "Could not setup the interfaces");
10495                                 return;
10496                         }
10497                 }
10498         } else {
10499                 interface_count = 0;
10500                 interfaces = NULL;
10501         }
10502
10503         mono_image_lock (klass->image);
10504
10505         if (!klass->interfaces_inited) {
10506                 klass->interface_count = interface_count;
10507                 klass->interfaces = interfaces;
10508
10509                 mono_memory_barrier ();
10510
10511                 klass->interfaces_inited = TRUE;
10512         }
10513
10514         mono_image_unlock (klass->image);
10515 }
10516
10517 static void
10518 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10519 {
10520         MonoClass *klass = field->parent;
10521         MonoImage *image = klass->image;
10522         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10523         MonoType *ftype;
10524         int field_idx = field - klass->fields;
10525
10526         mono_error_init (error);
10527
10528         if (gtd) {
10529                 MonoClassField *gfield = &gtd->fields [field_idx];
10530                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10531                 if (!mono_error_ok (error)) {
10532                         char *full_name = mono_type_get_full_name (gtd);
10533                         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));
10534                         g_free (full_name);
10535                 }
10536
10537                 ftype = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10538                 if (!mono_error_ok (error)) {
10539                         char *full_name = mono_type_get_full_name (klass);
10540                         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));
10541                         g_free (full_name);
10542                 }
10543         } else {
10544                 const char *sig;
10545                 guint32 cols [MONO_FIELD_SIZE];
10546                 MonoGenericContainer *container = NULL;
10547                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10548
10549                 /*FIXME, in theory we do not lazy load SRE fields*/
10550                 g_assert (!image_is_dynamic (image));
10551
10552                 if (mono_class_is_gtd (klass)) {
10553                         container = mono_class_get_generic_container (klass);
10554                 } else if (gtd) {
10555                         container = mono_class_get_generic_container (gtd);
10556                         g_assert (container);
10557                 }
10558
10559                 /* first_field_idx and idx points into the fieldptr table */
10560                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10561
10562                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10563                         char *full_name = mono_type_get_full_name (klass);
10564                         mono_error_set_type_load_class (error, klass, "Could not verify field '%s:%s' signature", full_name, field->name);;
10565                         mono_class_set_type_load_failure (klass, "%s", mono_error_get_message (error));
10566                         g_free (full_name);
10567                         return;
10568                 }
10569
10570                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10571
10572                 mono_metadata_decode_value (sig, &sig);
10573                 /* FIELD signature == 0x06 */
10574                 g_assert (*sig == 0x06);
10575
10576                 ftype = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10577                 if (!ftype) {
10578                         char *full_name = mono_type_get_full_name (klass);
10579                         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));
10580                         g_free (full_name);
10581                 }
10582         }
10583         mono_memory_barrier ();
10584         field->type = ftype;
10585 }
10586
10587 static guint32
10588 mono_field_resolve_flags (MonoClassField *field)
10589 {
10590         MonoClass *klass = field->parent;
10591         MonoImage *image = klass->image;
10592         MonoClass *gtd = mono_class_is_ginst (klass) ? mono_class_get_generic_type_definition (klass) : NULL;
10593         int field_idx = field - klass->fields;
10594
10595
10596         if (gtd) {
10597                 MonoClassField *gfield = &gtd->fields [field_idx];
10598                 return mono_field_get_flags (gfield);
10599         } else {
10600                 int idx = mono_class_get_first_field_idx (klass) + field_idx;
10601
10602                 /*FIXME, in theory we do not lazy load SRE fields*/
10603                 g_assert (!image_is_dynamic (image));
10604
10605                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10606         }
10607 }
10608
10609 /**
10610  * mono_class_get_fields_lazy:
10611  * @klass: the MonoClass to act on
10612  *
10613  * This routine is an iterator routine for retrieving the fields in a class.
10614  * Only minimal information about fields are loaded. Accessors must be used
10615  * for all MonoClassField returned.
10616  *
10617  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10618  * iterate over all of the elements.  When no more values are
10619  * available, the return value is NULL.
10620  *
10621  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10622  */
10623 MonoClassField*
10624 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10625 {
10626         MonoClassField* field;
10627         if (!iter)
10628                 return NULL;
10629         if (!*iter) {
10630                 mono_class_setup_basic_field_info (klass);
10631                 if (!klass->fields)
10632                         return NULL;
10633                 /* start from the first */
10634                 if (mono_class_get_field_count (klass)) {
10635                         *iter = &klass->fields [0];
10636                         return (MonoClassField *)*iter;
10637                 } else {
10638                         /* no fields */
10639                         return NULL;
10640                 }
10641         }
10642         field = (MonoClassField *)*iter;
10643         field++;
10644         if (field < &klass->fields [mono_class_get_field_count (klass)]) {
10645                 *iter = field;
10646                 return (MonoClassField *)*iter;
10647         }
10648         return NULL;
10649 }
10650
10651 char*
10652 mono_class_full_name (MonoClass *klass)
10653 {
10654         return mono_type_full_name (&klass->byval_arg);
10655 }
10656
10657 /* Declare all shared lazy type lookup functions */
10658 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)