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