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