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