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