First set of licensing changes
[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); /*FIXME proper error handling*/
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                 return mono_class_get_type ((MonoClass *)mono_lookup_dynamic_token (image, type_token, context));
7513
7514         if ((type_token & 0xff000000) != MONO_TOKEN_TYPE_SPEC) {
7515                 MonoClass *klass = mono_class_get_checked (image, type_token, error);
7516
7517                 if (!klass) {
7518                         mono_loader_assert_no_error ();
7519                         return NULL;
7520                 }
7521
7522                 g_assert (klass);
7523                 return mono_class_get_type (klass);
7524         }
7525
7526         type = mono_type_retrieve_from_typespec (image, type_token, context, &inflated, error);
7527
7528         if (!type) {
7529                 mono_loader_assert_no_error ();
7530                 return NULL;
7531         }
7532
7533         if (inflated) {
7534                 MonoType *tmp = type;
7535                 type = mono_class_get_type (mono_class_from_mono_type (type));
7536                 /* FIXME: This is a workaround fo the fact that a typespec token sometimes reference to the generic type definition.
7537                  * A MonoClass::byval_arg of a generic type definion has type CLASS.
7538                  * Some parts of mono create a GENERICINST to reference a generic type definition and this generates confict with byval_arg.
7539                  *
7540                  * The long term solution is to chaise this places and make then set MonoType::type correctly.
7541                  * */
7542                 if (type->type != tmp->type)
7543                         type = tmp;
7544                 else
7545                         mono_metadata_free_type (tmp);
7546         }
7547         return type;
7548 }
7549
7550 /**
7551  * mono_class_get:
7552  * @image: image where the class token will be looked up.
7553  * @type_token: a type token from the image
7554  *
7555  * Returns the MonoClass with the given @type_token on the @image
7556  */
7557 MonoClass *
7558 mono_class_get (MonoImage *image, guint32 type_token)
7559 {
7560         return mono_class_get_full (image, type_token, NULL);
7561 }
7562
7563 /**
7564  * mono_image_init_name_cache:
7565  *
7566  *  Initializes the class name cache stored in image->name_cache.
7567  *
7568  * LOCKING: Acquires the corresponding image lock.
7569  */
7570 void
7571 mono_image_init_name_cache (MonoImage *image)
7572 {
7573         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7574         guint32 cols [MONO_TYPEDEF_SIZE];
7575         const char *name;
7576         const char *nspace;
7577         guint32 i, visib, nspace_index;
7578         GHashTable *name_cache2, *nspace_table, *the_name_cache;
7579
7580         if (image->name_cache)
7581                 return;
7582
7583         the_name_cache = g_hash_table_new (g_str_hash, g_str_equal);
7584
7585         if (image_is_dynamic (image)) {
7586                 mono_image_lock (image);
7587                 if (image->name_cache) {
7588                         /* Somebody initialized it before us */
7589                         g_hash_table_destroy (the_name_cache);
7590                 } else {
7591                         mono_atomic_store_release (&image->name_cache, the_name_cache);
7592                 }
7593                 mono_image_unlock (image);
7594                 return;
7595         }
7596
7597         /* Temporary hash table to avoid lookups in the nspace_table */
7598         name_cache2 = g_hash_table_new (NULL, NULL);
7599
7600         for (i = 1; i <= t->rows; ++i) {
7601                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7602                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7603                 /*
7604                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7605                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7606                  */
7607                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7608                         continue;
7609                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7610                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7611
7612                 nspace_index = cols [MONO_TYPEDEF_NAMESPACE];
7613                 nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7614                 if (!nspace_table) {
7615                         nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7616                         g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7617                         g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7618                                                                  nspace_table);
7619                 }
7620                 g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (i));
7621         }
7622
7623         /* Load type names from EXPORTEDTYPES table */
7624         {
7625                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7626                 guint32 cols [MONO_EXP_TYPE_SIZE];
7627                 int i;
7628
7629                 for (i = 0; i < t->rows; ++i) {
7630                         mono_metadata_decode_row (t, i, cols, MONO_EXP_TYPE_SIZE);
7631
7632                         guint32 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7633                         if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_EXP_TYPE)
7634                                 /* Nested type */
7635                                 continue;
7636
7637                         name = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAME]);
7638                         nspace = mono_metadata_string_heap (image, cols [MONO_EXP_TYPE_NAMESPACE]);
7639
7640                         nspace_index = cols [MONO_EXP_TYPE_NAMESPACE];
7641                         nspace_table = (GHashTable *)g_hash_table_lookup (name_cache2, GUINT_TO_POINTER (nspace_index));
7642                         if (!nspace_table) {
7643                                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7644                                 g_hash_table_insert (the_name_cache, (char*)nspace, nspace_table);
7645                                 g_hash_table_insert (name_cache2, GUINT_TO_POINTER (nspace_index),
7646                                                                          nspace_table);
7647                         }
7648                         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (mono_metadata_make_token (MONO_TABLE_EXPORTEDTYPE, i + 1)));
7649                 }
7650         }
7651
7652         g_hash_table_destroy (name_cache2);
7653
7654         mono_image_lock (image);
7655         if (image->name_cache) {
7656                 /* Somebody initialized it before us */
7657                 g_hash_table_destroy (the_name_cache);
7658         } else {
7659                 mono_atomic_store_release (&image->name_cache, the_name_cache);
7660         }
7661         mono_image_unlock (image);
7662 }
7663
7664 /*FIXME Only dynamic assemblies should allow this operation.*/
7665 void
7666 mono_image_add_to_name_cache (MonoImage *image, const char *nspace, 
7667                                                           const char *name, guint32 index)
7668 {
7669         GHashTable *nspace_table;
7670         GHashTable *name_cache;
7671         guint32 old_index;
7672
7673         mono_image_init_name_cache (image);
7674         mono_image_lock (image);
7675
7676         name_cache = image->name_cache;
7677         if (!(nspace_table = (GHashTable *)g_hash_table_lookup (name_cache, nspace))) {
7678                 nspace_table = g_hash_table_new (g_str_hash, g_str_equal);
7679                 g_hash_table_insert (name_cache, (char *)nspace, (char *)nspace_table);
7680         }
7681
7682         if ((old_index = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, (char*) name))))
7683                 g_error ("overrwritting old token %x on image %s for type %s::%s", old_index, image->name, nspace, name);
7684
7685         g_hash_table_insert (nspace_table, (char *) name, GUINT_TO_POINTER (index));
7686
7687         mono_image_unlock (image);
7688 }
7689
7690 typedef struct {
7691         gconstpointer key;
7692         gpointer value;
7693 } FindUserData;
7694
7695 static void
7696 find_nocase (gpointer key, gpointer value, gpointer user_data)
7697 {
7698         char *name = (char*)key;
7699         FindUserData *data = (FindUserData*)user_data;
7700
7701         if (!data->value && (mono_utf8_strcasecmp (name, (char*)data->key) == 0))
7702                 data->value = value;
7703 }
7704
7705 /**
7706  * mono_class_from_name_case:
7707  * @image: The MonoImage where the type is looked up in
7708  * @name_space: the type namespace
7709  * @name: the type short name.
7710  * @deprecated: use the mono_class_from_name_case_checked variant instead.
7711  *
7712  * Obtains a MonoClass with a given namespace and a given name which
7713  * is located in the given MonoImage.   The namespace and name
7714  * lookups are case insensitive.
7715  */
7716 MonoClass *
7717 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
7718 {
7719         MonoError error;
7720         MonoClass *res = mono_class_from_name_case_checked (image, name_space, name, &error);
7721         mono_error_cleanup (&error);
7722
7723         return res;
7724 }
7725
7726 /**
7727  * mono_class_from_name_case:
7728  * @image: The MonoImage where the type is looked up in
7729  * @name_space: the type namespace
7730  * @name: the type short name.
7731  * @error: if 
7732  *
7733  * Obtains a MonoClass with a given namespace and a given name which
7734  * is located in the given MonoImage.   The namespace and name
7735  * lookups are case insensitive.
7736  *
7737  * Returns: The MonoClass if the given namespace and name were found, or NULL if it
7738  * was not found.   The @error object will contain information about the problem
7739  * in that case.
7740  */
7741 MonoClass *
7742 mono_class_from_name_case_checked (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7743 {
7744         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
7745         guint32 cols [MONO_TYPEDEF_SIZE];
7746         const char *n;
7747         const char *nspace;
7748         guint32 i, visib;
7749
7750         mono_error_init (error);
7751
7752         if (image_is_dynamic (image)) {
7753                 guint32 token = 0;
7754                 FindUserData user_data;
7755
7756                 mono_image_init_name_cache (image);
7757                 mono_image_lock (image);
7758
7759                 user_data.key = name_space;
7760                 user_data.value = NULL;
7761                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
7762
7763                 if (user_data.value) {
7764                         GHashTable *nspace_table = (GHashTable*)user_data.value;
7765
7766                         user_data.key = name;
7767                         user_data.value = NULL;
7768
7769                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
7770                         
7771                         if (user_data.value)
7772                                 token = GPOINTER_TO_UINT (user_data.value);
7773                 }
7774
7775                 mono_image_unlock (image);
7776                 
7777                 if (token)
7778                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | token, error);
7779                 else
7780                         return NULL;
7781
7782         }
7783
7784         /* add a cache if needed */
7785         for (i = 1; i <= t->rows; ++i) {
7786                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
7787                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
7788                 /*
7789                  * Nested types are accessed from the nesting name.  We use the fact that nested types use different visibility flags
7790                  * than toplevel types, thus avoiding the need to grovel through the NESTED_TYPE table
7791                  */
7792                 if (visib >= TYPE_ATTRIBUTE_NESTED_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM)
7793                         continue;
7794                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
7795                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
7796                 if (mono_utf8_strcasecmp (n, name) == 0 && mono_utf8_strcasecmp (nspace, name_space) == 0)
7797                         return mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | i, error);
7798         }
7799         return NULL;
7800 }
7801
7802 static MonoClass*
7803 return_nested_in (MonoClass *klass, char *nested)
7804 {
7805         MonoClass *found;
7806         char *s = strchr (nested, '/');
7807         gpointer iter = NULL;
7808
7809         if (s) {
7810                 *s = 0;
7811                 s++;
7812         }
7813
7814         while ((found = mono_class_get_nested_types (klass, &iter))) {
7815                 if (strcmp (found->name, nested) == 0) {
7816                         if (s)
7817                                 return return_nested_in (found, s);
7818                         return found;
7819                 }
7820         }
7821         return NULL;
7822 }
7823
7824 static MonoClass*
7825 search_modules (MonoImage *image, const char *name_space, const char *name, MonoError *error)
7826 {
7827         MonoTableInfo *file_table = &image->tables [MONO_TABLE_FILE];
7828         MonoImage *file_image;
7829         MonoClass *klass;
7830         int i;
7831
7832         mono_error_init (error);
7833
7834         /* 
7835          * The EXPORTEDTYPES table only contains public types, so have to search the
7836          * modules as well.
7837          * Note: image->modules contains the contents of the MODULEREF table, while
7838          * the real module list is in the FILE table.
7839          */
7840         for (i = 0; i < file_table->rows; i++) {
7841                 guint32 cols [MONO_FILE_SIZE];
7842                 mono_metadata_decode_row (file_table, i, cols, MONO_FILE_SIZE);
7843                 if (cols [MONO_FILE_FLAGS] == FILE_CONTAINS_NO_METADATA)
7844                         continue;
7845
7846                 file_image = mono_image_load_file_for_image (image, i + 1);
7847                 if (file_image) {
7848                         klass = mono_class_from_name_checked (file_image, name_space, name, error);
7849                         if (klass || !is_ok (error))
7850                                 return klass;
7851                 }
7852         }
7853
7854         return NULL;
7855 }
7856
7857 static MonoClass *
7858 mono_class_from_name_checked_aux (MonoImage *image, const char* name_space, const char *name, GHashTable* visited_images, MonoError *error)
7859 {
7860         GHashTable *nspace_table;
7861         MonoImage *loaded_image;
7862         guint32 token = 0;
7863         int i;
7864         MonoClass *klass;
7865         char *nested;
7866         char buf [1024];
7867
7868         mono_error_init (error);
7869
7870         // Checking visited images avoids stack overflows when cyclic references exist.
7871         if (g_hash_table_lookup (visited_images, image))
7872                 return NULL;
7873
7874         g_hash_table_insert (visited_images, image, GUINT_TO_POINTER(1));
7875
7876         if ((nested = strchr (name, '/'))) {
7877                 int pos = nested - name;
7878                 int len = strlen (name);
7879                 if (len > 1023)
7880                         return NULL;
7881                 memcpy (buf, name, len + 1);
7882                 buf [pos] = 0;
7883                 nested = buf + pos + 1;
7884                 name = buf;
7885         }
7886
7887         /* FIXME: get_class_from_name () can't handle types in the EXPORTEDTYPE table */
7888         if (get_class_from_name && image->tables [MONO_TABLE_EXPORTEDTYPE].rows == 0) {
7889                 gboolean res = get_class_from_name (image, name_space, name, &klass);
7890                 if (res) {
7891                         if (!klass) {
7892                                 klass = search_modules (image, name_space, name, error);
7893                                 if (!is_ok (error))
7894                                         return NULL;
7895                         }
7896                         if (nested)
7897                                 return klass ? return_nested_in (klass, nested) : NULL;
7898                         else
7899                                 return klass;
7900                 }
7901         }
7902
7903         mono_image_init_name_cache (image);
7904         mono_image_lock (image);
7905
7906         nspace_table = (GHashTable *)g_hash_table_lookup (image->name_cache, name_space);
7907
7908         if (nspace_table)
7909                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
7910
7911         mono_image_unlock (image);
7912
7913         if (!token && image_is_dynamic (image) && image->modules) {
7914                 /* Search modules as well */
7915                 for (i = 0; i < image->module_count; ++i) {
7916                         MonoImage *module = image->modules [i];
7917
7918                         klass = mono_class_from_name_checked (module, name_space, name, error);
7919                         if (klass || !is_ok (error))
7920                                 return klass;
7921                 }
7922         }
7923
7924         if (!token) {
7925                 klass = search_modules (image, name_space, name, error);
7926                 if (klass || !is_ok (error))
7927                         return klass;
7928         }
7929
7930         if (!token)
7931                 return NULL;
7932
7933         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
7934                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
7935                 guint32 cols [MONO_EXP_TYPE_SIZE];
7936                 guint32 idx, impl;
7937
7938                 idx = mono_metadata_token_index (token);
7939
7940                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
7941
7942                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
7943                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
7944                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
7945                         if (!loaded_image)
7946                                 return NULL;
7947                         klass = mono_class_from_name_checked_aux (loaded_image, name_space, name, visited_images, error);
7948                         if (nested)
7949                                 return klass ? return_nested_in (klass, nested) : NULL;
7950                         return klass;
7951                 } else if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_ASSEMBLYREF) {
7952                         guint32 assembly_idx;
7953
7954                         assembly_idx = impl >> MONO_IMPLEMENTATION_BITS;
7955
7956                         mono_assembly_load_reference (image, assembly_idx - 1);
7957                         g_assert (image->references [assembly_idx - 1]);
7958                         if (image->references [assembly_idx - 1] == (gpointer)-1)
7959                                 return NULL;                    
7960                         klass = mono_class_from_name_checked_aux (image->references [assembly_idx - 1]->image, name_space, name, visited_images, error);
7961                         if (nested)
7962                                 return klass ? return_nested_in (klass, nested) : NULL;
7963                         return klass;
7964                 } else {
7965                         g_assert_not_reached ();
7966                 }
7967         }
7968
7969         token = MONO_TOKEN_TYPE_DEF | token;
7970
7971         klass = mono_class_get_checked (image, token, error);
7972         if (nested)
7973                 return return_nested_in (klass, nested);
7974         return klass;
7975 }
7976
7977 /**
7978  * mono_class_from_name_checked:
7979  * @image: The MonoImage where the type is looked up in
7980  * @name_space: the type namespace
7981  * @name: the type short name.
7982  *
7983  * Obtains a MonoClass with a given namespace and a given name which
7984  * is located in the given MonoImage.
7985  *
7986  * Works like mono_class_from_name, but error handling is tricky. It can return NULL and have no error
7987  * set if the class was not found or it will return NULL and set the error if there was a loading error.
7988  */
7989 MonoClass *
7990 mono_class_from_name_checked (MonoImage *image, const char* name_space, const char *name, MonoError *error)
7991 {
7992         MonoClass *klass;
7993         GHashTable *visited_images;
7994
7995         visited_images = g_hash_table_new (g_direct_hash, g_direct_equal);
7996
7997         klass = mono_class_from_name_checked_aux (image, name_space, name, visited_images, error);
7998
7999         g_hash_table_destroy (visited_images);
8000
8001         return klass;
8002 }
8003
8004 /**
8005  * mono_class_from_name:
8006  * @image: The MonoImage where the type is looked up in
8007  * @name_space: the type namespace
8008  * @name: the type short name.
8009  *
8010  * Obtains a MonoClass with a given namespace and a given name which
8011  * is located in the given MonoImage.
8012  *
8013  * To reference nested classes, use the "/" character as a separator.
8014  * For example use "Foo/Bar" to reference the class Bar that is nested
8015  * inside Foo, like this: "class Foo { class Bar {} }".
8016  */
8017 MonoClass *
8018 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
8019 {
8020         MonoError error;
8021         MonoClass *klass;
8022
8023         klass = mono_class_from_name_checked (image, name_space, name, &error);
8024         mono_error_cleanup (&error); /* FIXME Don't swallow the error */
8025
8026         return klass;
8027 }
8028
8029 /**
8030  * mono_class_load_from_name:
8031  * @image: The MonoImage where the type is looked up in
8032  * @name_space: the type namespace
8033  * @name: the type short name.
8034  *
8035  * This function works exactly like mono_class_from_name but it will abort if the class is not found.
8036  * This function should be used by the runtime for critical types to which there's no way to recover but crash
8037  * If they are missing. Thing of System.Object or System.String.
8038  */
8039 MonoClass *
8040 mono_class_load_from_name (MonoImage *image, const char* name_space, const char *name)
8041 {
8042         MonoError error;
8043         MonoClass *klass;
8044
8045         klass = mono_class_from_name_checked (image, name_space, name, &error);
8046         if (!klass)
8047                 g_error ("Runtime critical type %s.%s not found", name_space, name);
8048         if (!mono_error_ok (&error))
8049                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8050         return klass;
8051 }
8052
8053 /**
8054  * mono_class_try_load_from_name:
8055  * @image: The MonoImage where the type is looked up in
8056  * @name_space: the type namespace
8057  * @name: the type short name.
8058  *
8059  * This function tries to load a type, returning the class was found or NULL otherwise.
8060  * This function should be used by the runtime when probing for optional types, those that could have being linked out.
8061  *
8062  * Big design consideration. This function aborts if there was an error loading the type. This prevents us from missing
8063  * a type that we would otherwise assume to be available but was not due some error.
8064  *
8065  */
8066 MonoClass*
8067 mono_class_try_load_from_name (MonoImage *image, const char* name_space, const char *name)
8068 {
8069         MonoError error;
8070         MonoClass *klass;
8071
8072         klass = mono_class_from_name_checked (image, name_space, name, &error);
8073         if (!mono_error_ok (&error))
8074                 g_error ("Could not load runtime critical type %s.%s due to %s", name_space, name, mono_error_get_message (&error));
8075         return klass;
8076 }
8077
8078
8079 /**
8080  * mono_class_is_subclass_of:
8081  * @klass: class to probe if it is a subclass of another one
8082  * @klassc: the class we suspect is the base class
8083  * @check_interfaces: whether we should perform interface checks
8084  *
8085  * This method determines whether @klass is a subclass of @klassc.
8086  *
8087  * If the @check_interfaces flag is set, then if @klassc is an interface
8088  * this method return TRUE if the @klass implements the interface or
8089  * if @klass is an interface, if one of its base classes is @klass.
8090  *
8091  * If @check_interfaces is false then, then if @klass is not an interface
8092  * then it returns TRUE if the @klass is a subclass of @klassc.
8093  *
8094  * if @klass is an interface and @klassc is System.Object, then this function
8095  * return true.
8096  *
8097  */
8098 gboolean
8099 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
8100                            gboolean check_interfaces)
8101 {
8102 /*FIXME test for interfaces with variant generic arguments*/
8103         
8104         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
8105                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (klass, klassc->interface_id))
8106                         return TRUE;
8107         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
8108                 int i;
8109
8110                 for (i = 0; i < klass->interface_count; i ++) {
8111                         MonoClass *ic =  klass->interfaces [i];
8112                         if (ic == klassc)
8113                                 return TRUE;
8114                 }
8115         } else {
8116                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
8117                         return TRUE;
8118         }
8119
8120         /* 
8121          * MS.NET thinks interfaces are a subclass of Object, so we think it as
8122          * well.
8123          */
8124         if (klassc == mono_defaults.object_class)
8125                 return TRUE;
8126
8127         return FALSE;
8128 }
8129
8130 static gboolean
8131 mono_type_is_generic_argument (MonoType *type)
8132 {
8133         return type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR;
8134 }
8135
8136 gboolean
8137 mono_class_has_variant_generic_params (MonoClass *klass)
8138 {
8139         int i;
8140         MonoGenericContainer *container;
8141
8142         if (!klass->generic_class)
8143                 return FALSE;
8144
8145         container = klass->generic_class->container_class->generic_container;
8146
8147         for (i = 0; i < container->type_argc; ++i)
8148                 if (mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))
8149                         return TRUE;
8150
8151         return FALSE;
8152 }
8153
8154 static gboolean
8155 mono_gparam_is_reference_conversible (MonoClass *target, MonoClass *candidate, gboolean check_for_reference_conv)
8156 {
8157         if (target == candidate)
8158                 return TRUE;
8159
8160         if (check_for_reference_conv &&
8161                 mono_type_is_generic_argument (&target->byval_arg) &&
8162                 mono_type_is_generic_argument (&candidate->byval_arg)) {
8163                 MonoGenericParam *gparam = candidate->byval_arg.data.generic_param;
8164                 MonoGenericParamInfo *pinfo = mono_generic_param_info (gparam);
8165
8166                 if (!pinfo || (pinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) == 0)
8167                         return FALSE;
8168         }
8169         if (!mono_class_is_assignable_from (target, candidate))
8170                 return FALSE;
8171         return TRUE;
8172 }
8173
8174 /**
8175  * @container the generic container from the GTD
8176  * @klass: the class to be assigned to
8177  * @oklass: the source class
8178  * 
8179  * Both @klass and @oklass must be instances of the same generic interface.
8180  *
8181  * Returns: TRUE if @klass can be assigned to a @klass variable
8182  */
8183 gboolean
8184 mono_class_is_variant_compatible (MonoClass *klass, MonoClass *oklass, gboolean check_for_reference_conv)
8185 {
8186         int j;
8187         MonoType **klass_argv, **oklass_argv;
8188         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8189         MonoGenericContainer *container = klass_gtd->generic_container;
8190
8191         if (klass == oklass)
8192                 return TRUE;
8193
8194         /*Viable candidates are instances of the same generic interface*/
8195         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8196                 return FALSE;
8197
8198         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8199         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8200
8201         for (j = 0; j < container->type_argc; ++j) {
8202                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8203                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8204
8205                 if (param1_class->valuetype != param2_class->valuetype || (param1_class->valuetype && param1_class != param2_class))
8206                         return FALSE;
8207
8208                 /*
8209                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8210                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8211                  */
8212                 if (param1_class != param2_class) {
8213                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8214                                 if (!mono_gparam_is_reference_conversible (param1_class, param2_class, check_for_reference_conv))
8215                                         return FALSE;
8216                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8217                                 if (!mono_gparam_is_reference_conversible (param2_class, param1_class, check_for_reference_conv))
8218                                         return FALSE;
8219                         } else
8220                                 return FALSE;
8221                 }
8222         }
8223         return TRUE;
8224 }
8225
8226 static gboolean
8227 mono_gparam_is_assignable_from (MonoClass *target, MonoClass *candidate)
8228 {
8229         MonoGenericParam *gparam, *ogparam;
8230         MonoGenericParamInfo *tinfo, *cinfo;
8231         MonoClass **candidate_class;
8232         gboolean class_constraint_satisfied, valuetype_constraint_satisfied;
8233         int tmask, cmask;
8234
8235         if (target == candidate)
8236                 return TRUE;
8237         if (target->byval_arg.type != candidate->byval_arg.type)
8238                 return FALSE;
8239
8240         gparam = target->byval_arg.data.generic_param;
8241         ogparam = candidate->byval_arg.data.generic_param;
8242         tinfo = mono_generic_param_info (gparam);
8243         cinfo = mono_generic_param_info (ogparam);
8244
8245         class_constraint_satisfied = FALSE;
8246         valuetype_constraint_satisfied = FALSE;
8247
8248         /*candidate must have a super set of target's special constraints*/
8249         tmask = tinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8250         cmask = cinfo->flags & GENERIC_PARAMETER_ATTRIBUTE_SPECIAL_CONSTRAINTS_MASK;
8251
8252         if (cinfo->constraints) {
8253                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8254                         MonoClass *cc = *candidate_class;
8255
8256                         if (mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8257                                 class_constraint_satisfied = TRUE;
8258                         else if (!mono_type_is_reference (&cc->byval_arg) && !MONO_CLASS_IS_INTERFACE (cc))
8259                                 valuetype_constraint_satisfied = TRUE;
8260                 }
8261         }
8262         class_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) != 0;
8263         valuetype_constraint_satisfied |= (cmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) != 0;
8264
8265         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_REFERENCE_TYPE_CONSTRAINT) && !class_constraint_satisfied)
8266                 return FALSE;
8267         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT) && !valuetype_constraint_satisfied)
8268                 return FALSE;
8269         if ((tmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) && !((cmask & GENERIC_PARAMETER_ATTRIBUTE_CONSTRUCTOR_CONSTRAINT) ||
8270                 valuetype_constraint_satisfied)) {
8271                 return FALSE;
8272         }
8273
8274
8275         /*candidate type constraints must be a superset of target's*/
8276         if (tinfo->constraints) {
8277                 MonoClass **target_class;
8278                 for (target_class = tinfo->constraints; *target_class; ++target_class) {
8279                         MonoClass *tc = *target_class;
8280
8281                         /*
8282                          * A constraint from @target might inflate into @candidate itself and in that case we don't need
8283                          * check it's constraints since it satisfy the constraint by itself.
8284                          */
8285                         if (mono_metadata_type_equal (&tc->byval_arg, &candidate->byval_arg))
8286                                 continue;
8287
8288                         if (!cinfo->constraints)
8289                                 return FALSE;
8290
8291                         for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8292                                 MonoClass *cc = *candidate_class;
8293
8294                                 if (mono_class_is_assignable_from (tc, cc))
8295                                         break;
8296
8297                                 /*
8298                                  * This happens when we have the following:
8299                                  *
8300                                  * Bar<K> where K : IFace
8301                                  * Foo<T, U> where T : U where U : IFace
8302                                  *      ...
8303                                  *      Bar<T> <- T here satisfy K constraint transitively through to U's constraint
8304                                  *
8305                                  */
8306                                 if (mono_type_is_generic_argument (&cc->byval_arg)) {
8307                                         if (mono_gparam_is_assignable_from (target, cc))
8308                                                 break;
8309                                 }
8310                         }
8311                         if (!*candidate_class)
8312                                 return FALSE;
8313                 }
8314         }
8315
8316         /*candidate itself must have a constraint that satisfy target*/
8317         if (cinfo->constraints) {
8318                 for (candidate_class = cinfo->constraints; *candidate_class; ++candidate_class) {
8319                         MonoClass *cc = *candidate_class;
8320                         if (mono_class_is_assignable_from (target, cc))
8321                                 return TRUE;
8322                 }
8323         }
8324         return FALSE;
8325 }
8326
8327 /**
8328  * mono_class_is_assignable_from:
8329  * @klass: the class to be assigned to
8330  * @oklass: the source class
8331  *
8332  * Returns: TRUE if an instance of object oklass can be assigned to an
8333  * instance of object @klass
8334  */
8335 gboolean
8336 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
8337 {
8338         MonoError error;
8339         /*FIXME this will cause a lot of irrelevant stuff to be loaded.*/
8340         if (!klass->inited)
8341                 mono_class_init (klass);
8342
8343         if (!oklass->inited)
8344                 mono_class_init (oklass);
8345
8346         if (mono_class_has_failure (klass) || mono_class_has_failure  (oklass))
8347                 return FALSE;
8348
8349         if (mono_type_is_generic_argument (&klass->byval_arg)) {
8350                 if (!mono_type_is_generic_argument (&oklass->byval_arg))
8351                         return FALSE;
8352                 return mono_gparam_is_assignable_from (klass, oklass);
8353         }
8354
8355         if (MONO_CLASS_IS_INTERFACE (klass)) {
8356                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR)) {
8357                         MonoGenericParam *gparam = oklass->byval_arg.data.generic_param;
8358                         MonoClass **constraints = mono_generic_container_get_param_info (gparam->owner, gparam->num)->constraints;
8359                         int i;
8360
8361                         if (constraints) {
8362                                 for (i = 0; constraints [i]; ++i) {
8363                                         if (mono_class_is_assignable_from (klass, constraints [i]))
8364                                                 return TRUE;
8365                                 }
8366                         }
8367
8368                         return FALSE;
8369                 }
8370
8371                 /* interface_offsets might not be set for dynamic classes */
8372                 if (oklass->ref_info_handle && !oklass->interface_bitmap) {
8373                         /* 
8374                          * oklass might be a generic type parameter but they have 
8375                          * interface_offsets set.
8376                          */
8377                         gboolean result = mono_reflection_call_is_assignable_to (oklass, klass, &error);
8378                         if (!is_ok (&error)) {
8379                                 mono_error_cleanup (&error);
8380                                 return FALSE;
8381                         }
8382                         return result;
8383                 }
8384                 if (!oklass->interface_bitmap)
8385                         /* Happens with generic instances of not-yet created dynamic types */
8386                         return FALSE;
8387                 if (MONO_CLASS_IMPLEMENTS_INTERFACE (oklass, klass->interface_id))
8388                         return TRUE;
8389
8390                 if (mono_class_has_variant_generic_params (klass)) {
8391                         int i;
8392                         mono_class_setup_interfaces (oklass, &error);
8393                         if (!mono_error_ok (&error)) {
8394                                 mono_error_cleanup (&error);
8395                                 return FALSE;
8396                         }
8397
8398                         /*klass is a generic variant interface, We need to extract from oklass a list of ifaces which are viable candidates.*/
8399                         for (i = 0; i < oklass->interface_offsets_count; ++i) {
8400                                 MonoClass *iface = oklass->interfaces_packed [i];
8401
8402                                 if (mono_class_is_variant_compatible (klass, iface, FALSE))
8403                                         return TRUE;
8404                         }
8405                 }
8406                 return FALSE;
8407         } else if (klass->delegate) {
8408                 if (mono_class_has_variant_generic_params (klass) && mono_class_is_variant_compatible (klass, oklass, FALSE))
8409                         return TRUE;
8410         }else if (klass->rank) {
8411                 MonoClass *eclass, *eoclass;
8412
8413                 if (oklass->rank != klass->rank)
8414                         return FALSE;
8415
8416                 /* vectors vs. one dimensional arrays */
8417                 if (oklass->byval_arg.type != klass->byval_arg.type)
8418                         return FALSE;
8419
8420                 eclass = klass->cast_class;
8421                 eoclass = oklass->cast_class;
8422
8423                 /* 
8424                  * a is b does not imply a[] is b[] when a is a valuetype, and
8425                  * b is a reference type.
8426                  */
8427
8428                 if (eoclass->valuetype) {
8429                         if ((eclass == mono_defaults.enum_class) || 
8430                                 (eclass == mono_defaults.enum_class->parent) ||
8431                                 (eclass == mono_defaults.object_class))
8432                                 return FALSE;
8433                 }
8434
8435                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8436         } else if (mono_class_is_nullable (klass)) {
8437                 if (mono_class_is_nullable (oklass))
8438                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
8439                 else
8440                         return mono_class_is_assignable_from (klass->cast_class, oklass);
8441         } else if (klass == mono_defaults.object_class)
8442                 return TRUE;
8443
8444         return mono_class_has_parent (oklass, klass);
8445 }       
8446
8447 /*Check if @oklass is variant compatible with @klass.*/
8448 static gboolean
8449 mono_class_is_variant_compatible_slow (MonoClass *klass, MonoClass *oklass)
8450 {
8451         int j;
8452         MonoType **klass_argv, **oklass_argv;
8453         MonoClass *klass_gtd = mono_class_get_generic_type_definition (klass);
8454         MonoGenericContainer *container = klass_gtd->generic_container;
8455
8456         /*Viable candidates are instances of the same generic interface*/
8457         if (mono_class_get_generic_type_definition (oklass) != klass_gtd || oklass == klass_gtd)
8458                 return FALSE;
8459
8460         klass_argv = &klass->generic_class->context.class_inst->type_argv [0];
8461         oklass_argv = &oklass->generic_class->context.class_inst->type_argv [0];
8462
8463         for (j = 0; j < container->type_argc; ++j) {
8464                 MonoClass *param1_class = mono_class_from_mono_type (klass_argv [j]);
8465                 MonoClass *param2_class = mono_class_from_mono_type (oklass_argv [j]);
8466
8467                 if (param1_class->valuetype != param2_class->valuetype)
8468                         return FALSE;
8469
8470                 /*
8471                  * The _VARIANT and _COVARIANT constants should read _COVARIANT and
8472                  * _CONTRAVARIANT, but they are in a public header so we can't fix it.
8473                  */
8474                 if (param1_class != param2_class) {
8475                         if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_VARIANT) {
8476                                 if (!mono_class_is_assignable_from_slow (param1_class, param2_class))
8477                                         return FALSE;
8478                         } else if (mono_generic_container_get_param_info (container, j)->flags & MONO_GEN_PARAM_COVARIANT) {
8479                                 if (!mono_class_is_assignable_from_slow (param2_class, param1_class))
8480                                         return FALSE;
8481                         } else
8482                                 return FALSE;
8483                 }
8484         }
8485         return TRUE;
8486 }
8487 /*Check if @candidate implements the interface @target*/
8488 static gboolean
8489 mono_class_implement_interface_slow (MonoClass *target, MonoClass *candidate)
8490 {
8491         MonoError error;
8492         int i;
8493         gboolean is_variant = mono_class_has_variant_generic_params (target);
8494
8495         if (is_variant && MONO_CLASS_IS_INTERFACE (candidate)) {
8496                 if (mono_class_is_variant_compatible_slow (target, candidate))
8497                         return TRUE;
8498         }
8499
8500         do {
8501                 if (candidate == target)
8502                         return TRUE;
8503
8504                 /*A TypeBuilder can have more interfaces on tb->interfaces than on candidate->interfaces*/
8505                 if (image_is_dynamic (candidate->image) && !candidate->wastypebuilder) {
8506                         MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder *)mono_class_get_ref_info (candidate);
8507                         int j;
8508                         if (tb && tb->interfaces) {
8509                                 for (j = mono_array_length (tb->interfaces) - 1; j >= 0; --j) {
8510                                         MonoReflectionType *iface = mono_array_get (tb->interfaces, MonoReflectionType*, j);
8511                                         MonoClass *iface_class;
8512
8513                                         /* we can't realize the type here since it can do pretty much anything. */
8514                                         if (!iface->type)
8515                                                 continue;
8516                                         iface_class = mono_class_from_mono_type (iface->type);
8517                                         if (iface_class == target)
8518                                                 return TRUE;
8519                                         if (is_variant && mono_class_is_variant_compatible_slow (target, iface_class))
8520                                                 return TRUE;
8521                                         if (mono_class_implement_interface_slow (target, iface_class))
8522                                                 return TRUE;
8523                                 }
8524                         }
8525                 } else {
8526                         /*setup_interfaces don't mono_class_init anything*/
8527                         /*FIXME this doesn't handle primitive type arrays.
8528                         ICollection<sbyte> x byte [] won't work because candidate->interfaces, for byte[], won't have IList<sbyte>.
8529                         A possible way to fix this would be to move that to setup_interfaces from setup_interface_offsets.
8530                         */
8531                         mono_class_setup_interfaces (candidate, &error);
8532                         if (!mono_error_ok (&error)) {
8533                                 mono_error_cleanup (&error);
8534                                 return FALSE;
8535                         }
8536
8537                         for (i = 0; i < candidate->interface_count; ++i) {
8538                                 if (candidate->interfaces [i] == target)
8539                                         return TRUE;
8540                                 
8541                                 if (is_variant && mono_class_is_variant_compatible_slow (target, candidate->interfaces [i]))
8542                                         return TRUE;
8543
8544                                  if (mono_class_implement_interface_slow (target, candidate->interfaces [i]))
8545                                         return TRUE;
8546                         }
8547                 }
8548                 candidate = candidate->parent;
8549         } while (candidate);
8550
8551         return FALSE;
8552 }
8553
8554 /*
8555  * Check if @oklass can be assigned to @klass.
8556  * This function does the same as mono_class_is_assignable_from but is safe to be used from mono_class_init context.
8557  */
8558 gboolean
8559 mono_class_is_assignable_from_slow (MonoClass *target, MonoClass *candidate)
8560 {
8561         if (candidate == target)
8562                 return TRUE;
8563         if (target == mono_defaults.object_class)
8564                 return TRUE;
8565
8566         if (mono_class_has_parent (candidate, target))
8567                 return TRUE;
8568
8569         /*If target is not an interface there is no need to check them.*/
8570         if (MONO_CLASS_IS_INTERFACE (target))
8571                 return mono_class_implement_interface_slow (target, candidate);
8572
8573         if (target->delegate && mono_class_has_variant_generic_params (target))
8574                 return mono_class_is_variant_compatible (target, candidate, FALSE);
8575
8576         if (target->rank) {
8577                 MonoClass *eclass, *eoclass;
8578
8579                 if (target->rank != candidate->rank)
8580                         return FALSE;
8581
8582                 /* vectors vs. one dimensional arrays */
8583                 if (target->byval_arg.type != candidate->byval_arg.type)
8584                         return FALSE;
8585
8586                 eclass = target->cast_class;
8587                 eoclass = candidate->cast_class;
8588
8589                 /*
8590                  * a is b does not imply a[] is b[] when a is a valuetype, and
8591                  * b is a reference type.
8592                  */
8593
8594                 if (eoclass->valuetype) {
8595                         if ((eclass == mono_defaults.enum_class) ||
8596                                 (eclass == mono_defaults.enum_class->parent) ||
8597                                 (eclass == mono_defaults.object_class))
8598                                 return FALSE;
8599                 }
8600
8601                 return mono_class_is_assignable_from_slow (target->cast_class, candidate->cast_class);
8602         }
8603         /*FIXME properly handle nullables */
8604         /*FIXME properly handle (M)VAR */
8605         return FALSE;
8606 }
8607
8608 /**
8609  * mono_class_get_cctor:
8610  * @klass: A MonoClass pointer
8611  *
8612  * Returns: The static constructor of @klass if it exists, NULL otherwise.
8613  */
8614 MonoMethod*
8615 mono_class_get_cctor (MonoClass *klass)
8616 {
8617         MonoCachedClassInfo cached_info;
8618
8619         if (image_is_dynamic (klass->image)) {
8620                 /* 
8621                  * has_cctor is not set for these classes because mono_class_init () is
8622                  * not run for them.
8623                  */
8624                 return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8625         }
8626
8627         if (!klass->has_cctor)
8628                 return NULL;
8629
8630         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8631                 MonoError error;
8632                 MonoMethod *result = mono_get_method_checked (klass->image, cached_info.cctor_token, klass, NULL, &error);
8633                 if (!mono_error_ok (&error))
8634                         g_error ("Could not lookup class cctor from cached metadata due to %s", mono_error_get_message (&error));
8635                 return result;
8636         }
8637
8638         if (klass->generic_class && !klass->methods)
8639                 return mono_class_get_inflated_method (klass, mono_class_get_cctor (klass->generic_class->container_class));
8640
8641         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
8642 }
8643
8644 /**
8645  * mono_class_get_finalizer:
8646  * @klass: The MonoClass pointer
8647  *
8648  * Returns: The finalizer method of @klass if it exists, NULL otherwise.
8649  */
8650 MonoMethod*
8651 mono_class_get_finalizer (MonoClass *klass)
8652 {
8653         MonoCachedClassInfo cached_info;
8654
8655         if (!klass->inited)
8656                 mono_class_init (klass);
8657         if (!mono_class_has_finalizer (klass))
8658                 return NULL;
8659
8660         if (mono_class_get_cached_class_info (klass, &cached_info)) {
8661                 MonoError error;
8662                 MonoMethod *result = mono_get_method_checked (cached_info.finalize_image, cached_info.finalize_token, NULL, NULL, &error);
8663                 if (!mono_error_ok (&error))
8664                         g_error ("Could not lookup finalizer from cached metadata due to %s", mono_error_get_message (&error));
8665                 return result;
8666         }else {
8667                 mono_class_setup_vtable (klass);
8668                 return klass->vtable [finalize_slot];
8669         }
8670 }
8671
8672 /**
8673  * mono_class_needs_cctor_run:
8674  * @klass: the MonoClass pointer
8675  * @caller: a MonoMethod describing the caller
8676  *
8677  * Determines whenever the class has a static constructor and whenever it
8678  * needs to be called when executing CALLER.
8679  */
8680 gboolean
8681 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
8682 {
8683         MonoMethod *method;
8684
8685         method = mono_class_get_cctor (klass);
8686         if (method)
8687                 return (method == caller) ? FALSE : TRUE;
8688         else
8689                 return FALSE;
8690 }
8691
8692 /**
8693  * mono_class_array_element_size:
8694  * @klass: 
8695  *
8696  * Returns: The number of bytes an element of type @klass
8697  * uses when stored into an array.
8698  */
8699 gint32
8700 mono_class_array_element_size (MonoClass *klass)
8701 {
8702         MonoType *type = &klass->byval_arg;
8703         
8704 handle_enum:
8705         switch (type->type) {
8706         case MONO_TYPE_I1:
8707         case MONO_TYPE_U1:
8708         case MONO_TYPE_BOOLEAN:
8709                 return 1;
8710         case MONO_TYPE_I2:
8711         case MONO_TYPE_U2:
8712         case MONO_TYPE_CHAR:
8713                 return 2;
8714         case MONO_TYPE_I4:
8715         case MONO_TYPE_U4:
8716         case MONO_TYPE_R4:
8717                 return 4;
8718         case MONO_TYPE_I:
8719         case MONO_TYPE_U:
8720         case MONO_TYPE_PTR:
8721         case MONO_TYPE_CLASS:
8722         case MONO_TYPE_STRING:
8723         case MONO_TYPE_OBJECT:
8724         case MONO_TYPE_SZARRAY:
8725         case MONO_TYPE_ARRAY: 
8726                 return sizeof (gpointer);
8727         case MONO_TYPE_I8:
8728         case MONO_TYPE_U8:
8729         case MONO_TYPE_R8:
8730                 return 8;
8731         case MONO_TYPE_VALUETYPE:
8732                 if (type->data.klass->enumtype) {
8733                         type = mono_class_enum_basetype (type->data.klass);
8734                         klass = klass->element_class;
8735                         goto handle_enum;
8736                 }
8737                 return mono_class_instance_size (klass) - sizeof (MonoObject);
8738         case MONO_TYPE_GENERICINST:
8739                 type = &type->data.generic_class->container_class->byval_arg;
8740                 goto handle_enum;
8741         case MONO_TYPE_VAR:
8742         case MONO_TYPE_MVAR: {
8743                 int align;
8744
8745                 return mono_type_size (type, &align);
8746         }
8747         case MONO_TYPE_VOID:
8748                 return 0;
8749                 
8750         default:
8751                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
8752         }
8753         return -1;
8754 }
8755
8756 /**
8757  * mono_array_element_size:
8758  * @ac: pointer to a #MonoArrayClass
8759  *
8760  * Returns: The size of single array element.
8761  */
8762 gint32
8763 mono_array_element_size (MonoClass *ac)
8764 {
8765         g_assert (ac->rank);
8766         return ac->sizes.element_size;
8767 }
8768
8769 gpointer
8770 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
8771               MonoGenericContext *context)
8772 {
8773         MonoError error;
8774         gpointer res = mono_ldtoken_checked (image, token, handle_class, context, &error);
8775         g_assert (mono_error_ok (&error));
8776         return res;
8777 }
8778
8779 gpointer
8780 mono_ldtoken_checked (MonoImage *image, guint32 token, MonoClass **handle_class,
8781               MonoGenericContext *context, MonoError *error)
8782 {
8783         mono_error_init (error);
8784
8785         if (image_is_dynamic (image)) {
8786                 MonoClass *tmp_handle_class;
8787                 gpointer obj = mono_lookup_dynamic_token_class (image, token, TRUE, &tmp_handle_class, context);
8788
8789                 g_assert (tmp_handle_class);
8790                 if (handle_class)
8791                         *handle_class = tmp_handle_class;
8792
8793                 if (tmp_handle_class == mono_defaults.typehandle_class)
8794                         return &((MonoClass*)obj)->byval_arg;
8795                 else
8796                         return obj;
8797         }
8798
8799         switch (token & 0xff000000) {
8800         case MONO_TOKEN_TYPE_DEF:
8801         case MONO_TOKEN_TYPE_REF:
8802         case MONO_TOKEN_TYPE_SPEC: {
8803                 MonoType *type;
8804                 if (handle_class)
8805                         *handle_class = mono_defaults.typehandle_class;
8806                 type = mono_type_get_checked (image, token, context, error);
8807                 if (!type)
8808                         return NULL;
8809
8810                 mono_class_init (mono_class_from_mono_type (type));
8811                 /* We return a MonoType* as handle */
8812                 return type;
8813         }
8814         case MONO_TOKEN_FIELD_DEF: {
8815                 MonoClass *klass;
8816                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
8817                 if (!type) {
8818                         mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8819                         return NULL;
8820                 }
8821                 if (handle_class)
8822                         *handle_class = mono_defaults.fieldhandle_class;
8823                 klass = mono_class_get_and_inflate_typespec_checked (image, MONO_TOKEN_TYPE_DEF | type, context, error);
8824                 if (!klass)
8825                         return NULL;
8826
8827                 mono_class_init (klass);
8828                 return mono_class_get_field (klass, token);
8829         }
8830         case MONO_TOKEN_METHOD_DEF:
8831         case MONO_TOKEN_METHOD_SPEC: {
8832                 MonoMethod *meth;
8833                 meth = mono_get_method_checked (image, token, NULL, context, error);
8834                 if (handle_class)
8835                         *handle_class = mono_defaults.methodhandle_class;
8836                 if (!meth)
8837                         return NULL;
8838
8839                 return meth;
8840         }
8841         case MONO_TOKEN_MEMBER_REF: {
8842                 guint32 cols [MONO_MEMBERREF_SIZE];
8843                 const char *sig;
8844                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
8845                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
8846                 mono_metadata_decode_blob_size (sig, &sig);
8847                 if (*sig == 0x6) { /* it's a field */
8848                         MonoClass *klass;
8849                         MonoClassField *field;
8850                         field = mono_field_from_token_checked (image, token, &klass, context, error);
8851                         if (handle_class)
8852                                 *handle_class = mono_defaults.fieldhandle_class;
8853                         return field;
8854                 } else {
8855                         MonoMethod *meth;
8856                         meth = mono_get_method_checked (image, token, NULL, context, error);
8857                         if (handle_class)
8858                                 *handle_class = mono_defaults.methodhandle_class;
8859                         return meth;
8860                 }
8861         }
8862         default:
8863                 mono_error_set_bad_image (error, image, "Bad ldtoken %x", token);
8864         }
8865         return NULL;
8866 }
8867
8868 /**
8869  * This function might need to call runtime functions so it can't be part
8870  * of the metadata library.
8871  */
8872 static MonoLookupDynamicToken lookup_dynamic = NULL;
8873
8874 void
8875 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
8876 {
8877         lookup_dynamic = func;
8878 }
8879
8880 gpointer
8881 mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *context)
8882 {
8883         MonoClass *handle_class;
8884
8885         return lookup_dynamic (image, token, TRUE, &handle_class, context);
8886 }
8887
8888 gpointer
8889 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean valid_token, MonoClass **handle_class, MonoGenericContext *context)
8890 {
8891         return lookup_dynamic (image, token, valid_token, handle_class, context);
8892 }
8893
8894 static MonoGetCachedClassInfo get_cached_class_info = NULL;
8895
8896 void
8897 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
8898 {
8899         get_cached_class_info = func;
8900 }
8901
8902 static gboolean
8903 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
8904 {
8905         if (!get_cached_class_info)
8906                 return FALSE;
8907         else
8908                 return get_cached_class_info (klass, res);
8909 }
8910
8911 void
8912 mono_install_get_class_from_name (MonoGetClassFromName func)
8913 {
8914         get_class_from_name = func;
8915 }
8916
8917 /**
8918  * mono_class_get_image:
8919  *
8920  * Use this method to get the `MonoImage*` where this class came from.
8921  *
8922  * Returns: The image where this class is defined.
8923  */
8924 MonoImage*
8925 mono_class_get_image (MonoClass *klass)
8926 {
8927         return klass->image;
8928 }
8929
8930 /**
8931  * mono_class_get_element_class:
8932  * @klass: the MonoClass to act on
8933  *
8934  * Use this function to get the element class of an array.
8935  *
8936  * Returns: The element class of an array.
8937  */
8938 MonoClass*
8939 mono_class_get_element_class (MonoClass *klass)
8940 {
8941         return klass->element_class;
8942 }
8943
8944 /**
8945  * mono_class_is_valuetype:
8946  * @klass: the MonoClass to act on
8947  *
8948  * Use this method to determine if the provided `MonoClass*` represents a value type,
8949  * or a reference type.
8950  *
8951  * Returns: TRUE if the MonoClass represents a ValueType, FALSE if it represents a reference type.
8952  */
8953 gboolean
8954 mono_class_is_valuetype (MonoClass *klass)
8955 {
8956         return klass->valuetype;
8957 }
8958
8959 /**
8960  * mono_class_is_enum:
8961  * @klass: the MonoClass to act on
8962  *
8963  * Use this function to determine if the provided `MonoClass*` represents an enumeration.
8964  *
8965  * Returns: TRUE if the MonoClass represents an enumeration.
8966  */
8967 gboolean
8968 mono_class_is_enum (MonoClass *klass)
8969 {
8970         return klass->enumtype;
8971 }
8972
8973 /**
8974  * mono_class_enum_basetype:
8975  * @klass: the MonoClass to act on
8976  *
8977  * Use this function to get the underlying type for an enumeration value.
8978  * 
8979  * Returns: The underlying type representation for an enumeration.
8980  */
8981 MonoType*
8982 mono_class_enum_basetype (MonoClass *klass)
8983 {
8984         if (klass->element_class == klass)
8985                 /* SRE or broken types */
8986                 return NULL;
8987         else
8988                 return &klass->element_class->byval_arg;
8989 }
8990
8991 /**
8992  * mono_class_get_parent
8993  * @klass: the MonoClass to act on
8994  *
8995  * Returns: The parent class for this class.
8996  */
8997 MonoClass*
8998 mono_class_get_parent (MonoClass *klass)
8999 {
9000         return klass->parent;
9001 }
9002
9003 /**
9004  * mono_class_get_nesting_type:
9005  * @klass: the MonoClass to act on
9006  *
9007  * Use this function to obtain the class that the provided `MonoClass*` is nested on.
9008  *
9009  * If the return is NULL, this indicates that this class is not nested.
9010  *
9011  * Returns: The container type where this type is nested or NULL if this type is not a nested type.
9012  */
9013 MonoClass*
9014 mono_class_get_nesting_type (MonoClass *klass)
9015 {
9016         return klass->nested_in;
9017 }
9018
9019 /**
9020  * mono_class_get_rank:
9021  * @klass: the MonoClass to act on
9022  *
9023  * Returns: The rank for the array (the number of dimensions).
9024  */
9025 int
9026 mono_class_get_rank (MonoClass *klass)
9027 {
9028         return klass->rank;
9029 }
9030
9031 /**
9032  * mono_class_get_flags:
9033  * @klass: the MonoClass to act on
9034  *
9035  * The type flags from the TypeDef table from the metadata.
9036  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
9037  * different values.
9038  *
9039  * Returns: The flags from the TypeDef table.
9040  */
9041 guint32
9042 mono_class_get_flags (MonoClass *klass)
9043 {
9044         return klass->flags;
9045 }
9046
9047 /**
9048  * mono_class_get_name
9049  * @klass: the MonoClass to act on
9050  *
9051  * Returns: The name of the class.
9052  */
9053 const char*
9054 mono_class_get_name (MonoClass *klass)
9055 {
9056         return klass->name;
9057 }
9058
9059 /**
9060  * mono_class_get_namespace:
9061  * @klass: the MonoClass to act on
9062  *
9063  * Returns: The namespace of the class.
9064  */
9065 const char*
9066 mono_class_get_namespace (MonoClass *klass)
9067 {
9068         return klass->name_space;
9069 }
9070
9071 /**
9072  * mono_class_get_type:
9073  * @klass: the MonoClass to act on
9074  *
9075  * This method returns the internal Type representation for the class.
9076  *
9077  * Returns: The MonoType from the class.
9078  */
9079 MonoType*
9080 mono_class_get_type (MonoClass *klass)
9081 {
9082         return &klass->byval_arg;
9083 }
9084
9085 /**
9086  * mono_class_get_type_token:
9087  * @klass: the MonoClass to act on
9088  *
9089  * This method returns type token for the class.
9090  *
9091  * Returns: The type token for the class.
9092  */
9093 guint32
9094 mono_class_get_type_token (MonoClass *klass)
9095 {
9096   return klass->type_token;
9097 }
9098
9099 /**
9100  * mono_class_get_byref_type:
9101  * @klass: the MonoClass to act on
9102  *
9103  * 
9104  */
9105 MonoType*
9106 mono_class_get_byref_type (MonoClass *klass)
9107 {
9108         return &klass->this_arg;
9109 }
9110
9111 /**
9112  * mono_class_num_fields:
9113  * @klass: the MonoClass to act on
9114  *
9115  * Returns: The number of static and instance fields in the class.
9116  */
9117 int
9118 mono_class_num_fields (MonoClass *klass)
9119 {
9120         return klass->field.count;
9121 }
9122
9123 /**
9124  * mono_class_num_methods:
9125  * @klass: the MonoClass to act on
9126  *
9127  * Returns: The number of methods in the class.
9128  */
9129 int
9130 mono_class_num_methods (MonoClass *klass)
9131 {
9132         return klass->method.count;
9133 }
9134
9135 /**
9136  * mono_class_num_properties
9137  * @klass: the MonoClass to act on
9138  *
9139  * Returns: The number of properties in the class.
9140  */
9141 int
9142 mono_class_num_properties (MonoClass *klass)
9143 {
9144         mono_class_setup_properties (klass);
9145
9146         return klass->ext->property.count;
9147 }
9148
9149 /**
9150  * mono_class_num_events:
9151  * @klass: the MonoClass to act on
9152  *
9153  * Returns: The number of events in the class.
9154  */
9155 int
9156 mono_class_num_events (MonoClass *klass)
9157 {
9158         mono_class_setup_events (klass);
9159
9160         return klass->ext->event.count;
9161 }
9162
9163 /**
9164  * mono_class_get_fields:
9165  * @klass: the MonoClass to act on
9166  *
9167  * This routine is an iterator routine for retrieving the fields in a class.
9168  *
9169  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9170  * iterate over all of the elements.  When no more values are
9171  * available, the return value is NULL.
9172  *
9173  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
9174  */
9175 MonoClassField*
9176 mono_class_get_fields (MonoClass* klass, gpointer *iter)
9177 {
9178         MonoClassField* field;
9179         if (!iter)
9180                 return NULL;
9181         if (!*iter) {
9182                 mono_class_setup_fields_locking (klass);
9183                 if (mono_class_has_failure (klass))
9184                         return NULL;
9185                 /* start from the first */
9186                 if (klass->field.count) {
9187                         *iter = &klass->fields [0];
9188                         return &klass->fields [0];
9189                 } else {
9190                         /* no fields */
9191                         return NULL;
9192                 }
9193         }
9194         field = (MonoClassField *)*iter;
9195         field++;
9196         if (field < &klass->fields [klass->field.count]) {
9197                 *iter = field;
9198                 return field;
9199         }
9200         return NULL;
9201 }
9202
9203 /**
9204  * mono_class_get_methods
9205  * @klass: the MonoClass to act on
9206  *
9207  * This routine is an iterator routine for retrieving the fields in a class.
9208  *
9209  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9210  * iterate over all of the elements.  When no more values are
9211  * available, the return value is NULL.
9212  *
9213  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
9214  */
9215 MonoMethod*
9216 mono_class_get_methods (MonoClass* klass, gpointer *iter)
9217 {
9218         MonoMethod** method;
9219         if (!iter)
9220                 return NULL;
9221         if (!*iter) {
9222                 mono_class_setup_methods (klass);
9223
9224                 /*
9225                  * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9226                  * FIXME we should better report this error to the caller
9227                  */
9228                 if (!klass->methods)
9229                         return NULL;
9230                 /* start from the first */
9231                 if (klass->method.count) {
9232                         *iter = &klass->methods [0];
9233                         return klass->methods [0];
9234                 } else {
9235                         /* no method */
9236                         return NULL;
9237                 }
9238         }
9239         method = (MonoMethod **)*iter;
9240         method++;
9241         if (method < &klass->methods [klass->method.count]) {
9242                 *iter = method;
9243                 return *method;
9244         }
9245         return NULL;
9246 }
9247
9248 /*
9249  * mono_class_get_virtual_methods:
9250  *
9251  *   Iterate over the virtual methods of KLASS.
9252  *
9253  * LOCKING: Assumes the loader lock is held (because of the klass->methods check).
9254  */
9255 static MonoMethod*
9256 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
9257 {
9258         MonoMethod** method;
9259         if (!iter)
9260                 return NULL;
9261         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9262                 if (!*iter) {
9263                         mono_class_setup_methods (klass);
9264                         /*
9265                          * We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9266                          * FIXME we should better report this error to the caller
9267                          */
9268                         if (!klass->methods)
9269                                 return NULL;
9270                         /* start from the first */
9271                         method = &klass->methods [0];
9272                 } else {
9273                         method = (MonoMethod **)*iter;
9274                         method++;
9275                 }
9276                 while (method < &klass->methods [klass->method.count]) {
9277                         if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
9278                                 break;
9279                         method ++;
9280                 }
9281                 if (method < &klass->methods [klass->method.count]) {
9282                         *iter = method;
9283                         return *method;
9284                 } else {
9285                         return NULL;
9286                 }
9287         } else {
9288                 /* Search directly in metadata to avoid calling setup_methods () */
9289                 MonoMethod *res = NULL;
9290                 int i, start_index;
9291
9292                 if (!*iter) {
9293                         start_index = 0;
9294                 } else {
9295                         start_index = GPOINTER_TO_UINT (*iter);
9296                 }
9297
9298                 for (i = start_index; i < klass->method.count; ++i) {
9299                         guint32 flags;
9300
9301                         /* klass->method.first points into the methodptr table */
9302                         flags = mono_metadata_decode_table_row_col (klass->image, MONO_TABLE_METHOD, klass->method.first + i, MONO_METHOD_FLAGS);
9303
9304                         if (flags & METHOD_ATTRIBUTE_VIRTUAL)
9305                                 break;
9306                 }
9307
9308                 if (i < klass->method.count) {
9309                         MonoError error;
9310                         res = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9311                         mono_error_cleanup (&error); /* FIXME don't swallow the error */
9312
9313                         /* Add 1 here so the if (*iter) check fails */
9314                         *iter = GUINT_TO_POINTER (i + 1);
9315                         return res;
9316                 } else {
9317                         return NULL;
9318                 }
9319         }
9320 }
9321
9322 /**
9323  * mono_class_get_properties:
9324  * @klass: the MonoClass to act on
9325  *
9326  * This routine is an iterator routine for retrieving the properties in a class.
9327  *
9328  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9329  * iterate over all of the elements.  When no more values are
9330  * available, the return value is NULL.
9331  *
9332  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
9333  */
9334 MonoProperty*
9335 mono_class_get_properties (MonoClass* klass, gpointer *iter)
9336 {
9337         MonoProperty* property;
9338         if (!iter)
9339                 return NULL;
9340         if (!*iter) {
9341                 mono_class_setup_properties (klass);
9342                 /* start from the first */
9343                 if (klass->ext->property.count) {
9344                         *iter = &klass->ext->properties [0];
9345                         return (MonoProperty *)*iter;
9346                 } else {
9347                         /* no fields */
9348                         return NULL;
9349                 }
9350         }
9351         property = (MonoProperty *)*iter;
9352         property++;
9353         if (property < &klass->ext->properties [klass->ext->property.count]) {
9354                 *iter = property;
9355                 return (MonoProperty *)*iter;
9356         }
9357         return NULL;
9358 }
9359
9360 /**
9361  * mono_class_get_events:
9362  * @klass: the MonoClass to act on
9363  *
9364  * This routine is an iterator routine for retrieving the properties in a class.
9365  *
9366  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9367  * iterate over all of the elements.  When no more values are
9368  * available, the return value is NULL.
9369  *
9370  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
9371  */
9372 MonoEvent*
9373 mono_class_get_events (MonoClass* klass, gpointer *iter)
9374 {
9375         MonoEvent* event;
9376         if (!iter)
9377                 return NULL;
9378         if (!*iter) {
9379                 mono_class_setup_events (klass);
9380                 /* start from the first */
9381                 if (klass->ext->event.count) {
9382                         *iter = &klass->ext->events [0];
9383                         return (MonoEvent *)*iter;
9384                 } else {
9385                         /* no fields */
9386                         return NULL;
9387                 }
9388         }
9389         event = (MonoEvent *)*iter;
9390         event++;
9391         if (event < &klass->ext->events [klass->ext->event.count]) {
9392                 *iter = event;
9393                 return (MonoEvent *)*iter;
9394         }
9395         return NULL;
9396 }
9397
9398 /**
9399  * mono_class_get_interfaces
9400  * @klass: the MonoClass to act on
9401  *
9402  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
9403  *
9404  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9405  * iterate over all of the elements.  When no more values are
9406  * available, the return value is NULL.
9407  *
9408  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9409  */
9410 MonoClass*
9411 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
9412 {
9413         MonoError error;
9414         MonoClass** iface;
9415         if (!iter)
9416                 return NULL;
9417         if (!*iter) {
9418                 if (!klass->inited)
9419                         mono_class_init (klass);
9420                 if (!klass->interfaces_inited) {
9421                         mono_class_setup_interfaces (klass, &error);
9422                         if (!mono_error_ok (&error)) {
9423                                 mono_error_cleanup (&error);
9424                                 return NULL;
9425                         }
9426                 }
9427                 /* start from the first */
9428                 if (klass->interface_count) {
9429                         *iter = &klass->interfaces [0];
9430                         return klass->interfaces [0];
9431                 } else {
9432                         /* no interface */
9433                         return NULL;
9434                 }
9435         }
9436         iface = (MonoClass **)*iter;
9437         iface++;
9438         if (iface < &klass->interfaces [klass->interface_count]) {
9439                 *iter = iface;
9440                 return *iface;
9441         }
9442         return NULL;
9443 }
9444
9445 static void
9446 setup_nested_types (MonoClass *klass)
9447 {
9448         MonoError error;
9449         GList *classes, *nested_classes, *l;
9450         int i;
9451
9452         if (klass->nested_classes_inited)
9453                 return;
9454
9455         if (!klass->type_token)
9456                 klass->nested_classes_inited = TRUE;
9457
9458         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, 1);
9459         classes = NULL;
9460         while (i) {
9461                 MonoClass* nclass;
9462                 guint32 cols [MONO_NESTED_CLASS_SIZE];
9463                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
9464                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED], &error);
9465                 if (!mono_error_ok (&error)) {
9466                         /*FIXME don't swallow the error message*/
9467                         mono_error_cleanup (&error);
9468
9469                         i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9470                         continue;
9471                 }
9472
9473                 classes = g_list_prepend (classes, nclass);
9474
9475                 i = mono_metadata_nesting_typedef (klass->image, klass->type_token, i + 1);
9476         }
9477
9478         mono_class_alloc_ext (klass);
9479
9480         nested_classes = NULL;
9481         for (l = classes; l; l = l->next)
9482                 nested_classes = g_list_prepend_image (klass->image, nested_classes, l->data);
9483         g_list_free (classes);
9484
9485         mono_image_lock (klass->image);
9486
9487         mono_memory_barrier ();
9488         if (!klass->nested_classes_inited) {
9489                 klass->ext->nested_classes = nested_classes;
9490                 mono_memory_barrier ();
9491                 klass->nested_classes_inited = TRUE;
9492         }
9493
9494         mono_image_unlock (klass->image);
9495 }
9496
9497 /**
9498  * mono_class_get_nested_types
9499  * @klass: the MonoClass to act on
9500  *
9501  * This routine is an iterator routine for retrieving the nested types of a class.
9502  * This works only if @klass is non-generic, or a generic type definition.
9503  *
9504  * You must pass a gpointer that points to zero and is treated as an opaque handle to
9505  * iterate over all of the elements.  When no more values are
9506  * available, the return value is NULL.
9507  *
9508  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
9509  */
9510 MonoClass*
9511 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
9512 {
9513         GList *item;
9514
9515         if (!iter)
9516                 return NULL;
9517         if (!klass->nested_classes_inited)
9518                 setup_nested_types (klass);
9519
9520         if (!*iter) {
9521                 /* start from the first */
9522                 if (klass->ext && klass->ext->nested_classes) {
9523                         *iter = klass->ext->nested_classes;
9524                         return (MonoClass *)klass->ext->nested_classes->data;
9525                 } else {
9526                         /* no nested types */
9527                         return NULL;
9528                 }
9529         }
9530         item = (GList *)*iter;
9531         item = item->next;
9532         if (item) {
9533                 *iter = item;
9534                 return (MonoClass *)item->data;
9535         }
9536         return NULL;
9537 }
9538
9539
9540 /**
9541  * mono_class_is_delegate
9542  * @klass: the MonoClass to act on
9543  *
9544  * Returns: TRUE if the MonoClass represents a System.Delegate.
9545  */
9546 mono_bool
9547 mono_class_is_delegate (MonoClass *klass)
9548 {
9549         return klass->delegate;
9550 }
9551
9552 /**
9553  * mono_class_implements_interface
9554  * @klass: The MonoClass to act on
9555  * @interface: The interface to check if @klass implements.
9556  *
9557  * Returns: TRUE if @klass implements @interface.
9558  */
9559 mono_bool
9560 mono_class_implements_interface (MonoClass* klass, MonoClass* iface)
9561 {
9562         return mono_class_is_assignable_from (iface, klass);
9563 }
9564
9565 /**
9566  * mono_field_get_name:
9567  * @field: the MonoClassField to act on
9568  *
9569  * Returns: The name of the field.
9570  */
9571 const char*
9572 mono_field_get_name (MonoClassField *field)
9573 {
9574         return field->name;
9575 }
9576
9577 /**
9578  * mono_field_get_type:
9579  * @field: the MonoClassField to act on
9580  *
9581  * Returns: MonoType of the field.
9582  */
9583 MonoType*
9584 mono_field_get_type (MonoClassField *field)
9585 {
9586         MonoError error;
9587         MonoType *type = mono_field_get_type_checked (field, &error);
9588         if (!mono_error_ok (&error)) {
9589                 mono_trace_warning (MONO_TRACE_TYPE, "Could not load field's type due to %s", mono_error_get_message (&error));
9590                 mono_error_cleanup (&error);
9591         }
9592         return type;
9593 }
9594
9595
9596 /**
9597  * mono_field_get_type_checked:
9598  * @field: the MonoClassField to act on
9599  * @error: used to return any erro found while retrieving @field type
9600  *
9601  * Returns: MonoType of the field.
9602  */
9603 MonoType*
9604 mono_field_get_type_checked (MonoClassField *field, MonoError *error)
9605 {
9606         mono_error_init (error);
9607         if (!field->type)
9608                 mono_field_resolve_type (field, error);
9609         return field->type;
9610 }
9611
9612 /**
9613  * mono_field_get_parent:
9614  * @field: the MonoClassField to act on
9615  *
9616  * Returns: MonoClass where the field was defined.
9617  */
9618 MonoClass*
9619 mono_field_get_parent (MonoClassField *field)
9620 {
9621         return field->parent;
9622 }
9623
9624 /**
9625  * mono_field_get_flags;
9626  * @field: the MonoClassField to act on
9627  *
9628  * The metadata flags for a field are encoded using the
9629  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9630  *
9631  * Returns: The flags for the field.
9632  */
9633 guint32
9634 mono_field_get_flags (MonoClassField *field)
9635 {
9636         if (!field->type)
9637                 return mono_field_resolve_flags (field);
9638         return field->type->attrs;
9639 }
9640
9641 /**
9642  * mono_field_get_offset:
9643  * @field: the MonoClassField to act on
9644  *
9645  * Returns: The field offset.
9646  */
9647 guint32
9648 mono_field_get_offset (MonoClassField *field)
9649 {
9650         return field->offset;
9651 }
9652
9653 static const char *
9654 mono_field_get_rva (MonoClassField *field)
9655 {
9656         guint32 rva;
9657         int field_index;
9658         MonoClass *klass = field->parent;
9659         MonoFieldDefaultValue *field_def_values;
9660
9661         g_assert (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA);
9662
9663         if (!klass->ext || !klass->ext->field_def_values) {
9664                 mono_class_alloc_ext (klass);
9665
9666                 field_def_values = (MonoFieldDefaultValue *)mono_class_alloc0 (klass, sizeof (MonoFieldDefaultValue) * klass->field.count);
9667
9668                 mono_image_lock (klass->image);
9669                 if (!klass->ext->field_def_values)
9670                         klass->ext->field_def_values = field_def_values;
9671                 mono_image_unlock (klass->image);
9672         }
9673
9674         field_index = mono_field_get_index (field);
9675                 
9676         if (!klass->ext->field_def_values [field_index].data && !image_is_dynamic (klass->image)) {
9677                 mono_metadata_field_info (field->parent->image, klass->field.first + field_index, NULL, &rva, NULL);
9678                 if (!rva)
9679                         g_warning ("field %s in %s should have RVA data, but hasn't", mono_field_get_name (field), field->parent->name);
9680                 klass->ext->field_def_values [field_index].data = mono_image_rva_map (field->parent->image, rva);
9681         }
9682
9683         return klass->ext->field_def_values [field_index].data;
9684 }
9685
9686 /**
9687  * mono_field_get_data:
9688  * @field: the MonoClassField to act on
9689  *
9690  * Returns: A pointer to the metadata constant value or to the field
9691  * data if it has an RVA flag.
9692  */
9693 const char *
9694 mono_field_get_data (MonoClassField *field)
9695 {
9696         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT) {
9697                 MonoTypeEnum def_type;
9698
9699                 return mono_class_get_field_default_value (field, &def_type);
9700         } else if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
9701                 return mono_field_get_rva (field);
9702         } else {
9703                 return NULL;
9704         }
9705 }
9706
9707 /**
9708  * mono_property_get_name: 
9709  * @prop: the MonoProperty to act on
9710  *
9711  * Returns: The name of the property
9712  */
9713 const char*
9714 mono_property_get_name (MonoProperty *prop)
9715 {
9716         return prop->name;
9717 }
9718
9719 /**
9720  * mono_property_get_set_method
9721  * @prop: the MonoProperty to act on.
9722  *
9723  * Returns: The setter method of the property (A MonoMethod)
9724  */
9725 MonoMethod*
9726 mono_property_get_set_method (MonoProperty *prop)
9727 {
9728         return prop->set;
9729 }
9730
9731 /**
9732  * mono_property_get_get_method
9733  * @prop: the MonoProperty to act on.
9734  *
9735  * Returns: The setter method of the property (A MonoMethod)
9736  */
9737 MonoMethod*
9738 mono_property_get_get_method (MonoProperty *prop)
9739 {
9740         return prop->get;
9741 }
9742
9743 /**
9744  * mono_property_get_parent:
9745  * @prop: the MonoProperty to act on.
9746  *
9747  * Returns: The MonoClass where the property was defined.
9748  */
9749 MonoClass*
9750 mono_property_get_parent (MonoProperty *prop)
9751 {
9752         return prop->parent;
9753 }
9754
9755 /**
9756  * mono_property_get_flags:
9757  * @prop: the MonoProperty to act on.
9758  *
9759  * The metadata flags for a property are encoded using the
9760  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
9761  *
9762  * Returns: The flags for the property.
9763  */
9764 guint32
9765 mono_property_get_flags (MonoProperty *prop)
9766 {
9767         return prop->attrs;
9768 }
9769
9770 /**
9771  * mono_event_get_name:
9772  * @event: the MonoEvent to act on
9773  *
9774  * Returns: The name of the event.
9775  */
9776 const char*
9777 mono_event_get_name (MonoEvent *event)
9778 {
9779         return event->name;
9780 }
9781
9782 /**
9783  * mono_event_get_add_method:
9784  * @event: The MonoEvent to act on.
9785  *
9786  * Returns: The @add' method for the event (a MonoMethod).
9787  */
9788 MonoMethod*
9789 mono_event_get_add_method (MonoEvent *event)
9790 {
9791         return event->add;
9792 }
9793
9794 /**
9795  * mono_event_get_remove_method:
9796  * @event: The MonoEvent to act on.
9797  *
9798  * Returns: The @remove method for the event (a MonoMethod).
9799  */
9800 MonoMethod*
9801 mono_event_get_remove_method (MonoEvent *event)
9802 {
9803         return event->remove;
9804 }
9805
9806 /**
9807  * mono_event_get_raise_method:
9808  * @event: The MonoEvent to act on.
9809  *
9810  * Returns: The @raise method for the event (a MonoMethod).
9811  */
9812 MonoMethod*
9813 mono_event_get_raise_method (MonoEvent *event)
9814 {
9815         return event->raise;
9816 }
9817
9818 /**
9819  * mono_event_get_parent:
9820  * @event: the MonoEvent to act on.
9821  *
9822  * Returns: The MonoClass where the event is defined.
9823  */
9824 MonoClass*
9825 mono_event_get_parent (MonoEvent *event)
9826 {
9827         return event->parent;
9828 }
9829
9830 /**
9831  * mono_event_get_flags
9832  * @event: the MonoEvent to act on.
9833  *
9834  * The metadata flags for an event are encoded using the
9835  * EVENT_* constants.  See the tabledefs.h file for details.
9836  *
9837  * Returns: The flags for the event.
9838  */
9839 guint32
9840 mono_event_get_flags (MonoEvent *event)
9841 {
9842         return event->attrs;
9843 }
9844
9845 /**
9846  * mono_class_get_method_from_name:
9847  * @klass: where to look for the method
9848  * @name: name of the method
9849  * @param_count: number of parameters. -1 for any number.
9850  *
9851  * Obtains a MonoMethod with a given name and number of parameters.
9852  * It only works if there are no multiple signatures for any given method name.
9853  */
9854 MonoMethod *
9855 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
9856 {
9857         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
9858 }
9859
9860 static MonoMethod*
9861 find_method_in_metadata (MonoClass *klass, const char *name, int param_count, int flags)
9862 {
9863         MonoMethod *res = NULL;
9864         int i;
9865
9866         /* Search directly in the metadata to avoid calling setup_methods () */
9867         for (i = 0; i < klass->method.count; ++i) {
9868                 MonoError error;
9869                 guint32 cols [MONO_METHOD_SIZE];
9870                 MonoMethod *method;
9871                 MonoMethodSignature *sig;
9872
9873                 /* klass->method.first points into the methodptr table */
9874                 mono_metadata_decode_table_row (klass->image, MONO_TABLE_METHOD, klass->method.first + i, cols, MONO_METHOD_SIZE);
9875
9876                 if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
9877                         method = mono_get_method_checked (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass, NULL, &error);
9878                         if (!method) {
9879                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9880                                 continue;
9881                         }
9882                         if (param_count == -1) {
9883                                 res = method;
9884                                 break;
9885                         }
9886                         sig = mono_method_signature_checked (method, &error);
9887                         if (!sig) {
9888                                 mono_error_cleanup (&error); /* FIXME don't swallow the error */
9889                                 continue;
9890                         }
9891                         if (sig->param_count == param_count) {
9892                                 res = method;
9893                                 break;
9894                         }
9895                 }
9896         }
9897
9898         return res;
9899 }
9900
9901 /**
9902  * mono_class_get_method_from_name_flags:
9903  * @klass: where to look for the method
9904  * @name_space: name of the method
9905  * @param_count: number of parameters. -1 for any number.
9906  * @flags: flags which must be set in the method
9907  *
9908  * Obtains a MonoMethod with a given name and number of parameters.
9909  * It only works if there are no multiple signatures for any given method name.
9910  */
9911 MonoMethod *
9912 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
9913 {
9914         MonoMethod *res = NULL;
9915         int i;
9916
9917         mono_class_init (klass);
9918
9919         if (klass->generic_class && !klass->methods) {
9920                 res = mono_class_get_method_from_name_flags (klass->generic_class->container_class, name, param_count, flags);
9921                 if (res) {
9922                         MonoError error;
9923                         res = mono_class_inflate_generic_method_full_checked (res, klass, mono_class_get_context (klass), &error);
9924                         if (!mono_error_ok (&error))
9925                                 mono_error_cleanup (&error); /*FIXME don't swallow the error */
9926                 }
9927                 return res;
9928         }
9929
9930         if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
9931                 mono_class_setup_methods (klass);
9932                 /*
9933                 We can't fail lookup of methods otherwise the runtime will burst in flames on all sort of places.
9934                 See mono/tests/array_load_exception.il
9935                 FIXME we should better report this error to the caller
9936                  */
9937                 if (!klass->methods)
9938                         return NULL;
9939                 for (i = 0; i < klass->method.count; ++i) {
9940                         MonoMethod *method = klass->methods [i];
9941
9942                         if (method->name[0] == name [0] && 
9943                                 !strcmp (name, method->name) &&
9944                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
9945                                 ((method->flags & flags) == flags)) {
9946                                 res = method;
9947                                 break;
9948                         }
9949                 }
9950         }
9951         else {
9952             res = find_method_in_metadata (klass, name, param_count, flags);
9953         }
9954
9955         return res;
9956 }
9957
9958 /**
9959  * mono_class_set_failure:
9960  * @klass: class in which the failure was detected
9961  * @ex_type: the kind of exception/error to be thrown (later)
9962  * @ex_data: exception data (specific to each type of exception/error)
9963  *
9964  * Keep a detected failure informations in the class for later processing.
9965  * Note that only the first failure is kept.
9966  *
9967  * LOCKING: Acquires the loader lock.
9968  */
9969 gboolean
9970 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
9971 {
9972         if (mono_class_has_failure (klass))
9973                 return FALSE;
9974
9975         mono_loader_lock ();
9976         klass->exception_type = ex_type;
9977         if (ex_data)
9978                 mono_image_property_insert (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA, ex_data);
9979         mono_loader_unlock ();
9980
9981         return TRUE;
9982 }
9983
9984 /*
9985  * mono_class_get_exception_data:
9986  *
9987  *   Return the exception_data property of KLASS.
9988  *
9989  * LOCKING: Acquires the loader lock.
9990  */
9991 gpointer
9992 mono_class_get_exception_data (MonoClass *klass)
9993 {
9994         return mono_image_property_lookup (klass->image, klass, MONO_CLASS_PROP_EXCEPTION_DATA);
9995 }
9996
9997 /**
9998  * mono_classes_init:
9999  *
10000  * Initialize the resources used by this module.
10001  */
10002 void
10003 mono_classes_init (void)
10004 {
10005         mono_os_mutex_init (&classes_mutex);
10006
10007         mono_counters_register ("Inflated methods size",
10008                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_methods_size);
10009         mono_counters_register ("Inflated classes",
10010                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes);
10011         mono_counters_register ("Inflated classes size",
10012                                                         MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &inflated_classes_size);
10013         mono_counters_register ("MonoClass size",
10014                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &classes_size);
10015         mono_counters_register ("MonoClassExt size",
10016                                                         MONO_COUNTER_METADATA | MONO_COUNTER_INT, &class_ext_size);
10017 }
10018
10019 /**
10020  * mono_classes_cleanup:
10021  *
10022  * Free the resources used by this module.
10023  */
10024 void
10025 mono_classes_cleanup (void)
10026 {
10027         if (global_interface_bitset)
10028                 mono_bitset_free (global_interface_bitset);
10029         global_interface_bitset = NULL;
10030         mono_os_mutex_destroy (&classes_mutex);
10031 }
10032
10033 /**
10034  * mono_class_get_exception_for_failure:
10035  * @klass: class in which the failure was detected
10036  *
10037  * Return a constructed MonoException than the caller can then throw
10038  * using mono_raise_exception - or NULL if no failure is present (or
10039  * doesn't result in an exception).
10040  */
10041 MonoException*
10042 mono_class_get_exception_for_failure (MonoClass *klass)
10043 {
10044         gpointer exception_data = mono_class_get_exception_data (klass);
10045
10046         switch (mono_class_get_failure(klass)) {
10047         case MONO_EXCEPTION_TYPE_LOAD: {
10048                 MonoString *name;
10049                 MonoException *ex;
10050                 char *str = mono_type_get_full_name (klass);
10051                 char *astr = klass->image->assembly? mono_stringify_assembly_name (&klass->image->assembly->aname): NULL;
10052                 name = mono_string_new (mono_domain_get (), str);
10053                 g_free (str);
10054                 ex = mono_get_exception_type_load (name, astr);
10055                 g_free (astr);
10056                 return ex;
10057         }
10058         case MONO_EXCEPTION_MISSING_METHOD: {
10059                 char *class_name = (char *)exception_data;
10060                 char *assembly_name = class_name + strlen (class_name) + 1;
10061
10062                 return mono_get_exception_missing_method (class_name, assembly_name);
10063         }
10064         case MONO_EXCEPTION_MISSING_FIELD: {
10065                 char *class_name = (char *)exception_data;
10066                 char *member_name = class_name + strlen (class_name) + 1;
10067
10068                 return mono_get_exception_missing_field (class_name, member_name);
10069         }
10070         case MONO_EXCEPTION_FILE_NOT_FOUND: {
10071                 char *msg_format = (char *)exception_data;
10072                 char *assembly_name = msg_format + strlen (msg_format) + 1;
10073                 char *msg = g_strdup_printf (msg_format, assembly_name);
10074                 MonoException *ex;
10075
10076                 ex = mono_get_exception_file_not_found2 (msg, mono_string_new (mono_domain_get (), assembly_name));
10077
10078                 g_free (msg);
10079
10080                 return ex;
10081         }
10082         case MONO_EXCEPTION_BAD_IMAGE: {
10083                 return mono_get_exception_bad_image_format ((const char *)exception_data);
10084         }
10085         case MONO_EXCEPTION_INVALID_PROGRAM: {
10086                 return mono_exception_from_name_msg (mono_defaults.corlib, "System", "InvalidProgramException", "");
10087         }
10088         default: {
10089                 MonoLoaderError *error;
10090                 MonoException *ex;
10091                 
10092                 error = mono_loader_get_last_error ();
10093                 if (error != NULL){
10094                         ex = mono_loader_error_prepare_exception (error);
10095                         return ex;
10096                 }
10097                 
10098                 /* TODO - handle other class related failures */
10099                 return NULL;
10100         }
10101         }
10102 }
10103
10104 static gboolean
10105 is_nesting_type (MonoClass *outer_klass, MonoClass *inner_klass)
10106  {
10107         outer_klass = mono_class_get_generic_type_definition (outer_klass);
10108         inner_klass = mono_class_get_generic_type_definition (inner_klass);
10109         do {
10110                 if (outer_klass == inner_klass)
10111                         return TRUE;
10112                 inner_klass = inner_klass->nested_in;
10113         } while (inner_klass);
10114         return FALSE;
10115 }
10116
10117 MonoClass *
10118 mono_class_get_generic_type_definition (MonoClass *klass)
10119 {
10120         return klass->generic_class ? klass->generic_class->container_class : klass;
10121 }
10122
10123 /*
10124  * Check if @klass is a subtype of @parent ignoring generic instantiations.
10125  * 
10126  * Generic instantiations are ignored for all super types of @klass.
10127  * 
10128  * Visibility checks ignoring generic instantiations.  
10129  */
10130 gboolean
10131 mono_class_has_parent_and_ignore_generics (MonoClass *klass, MonoClass *parent)
10132 {
10133         int i;
10134         klass = mono_class_get_generic_type_definition (klass);
10135         parent = mono_class_get_generic_type_definition (parent);
10136         mono_class_setup_supertypes (klass);
10137
10138         for (i = 0; i < klass->idepth; ++i) {
10139                 if (parent == mono_class_get_generic_type_definition (klass->supertypes [i]))
10140                         return TRUE;
10141         }
10142         return FALSE;
10143 }
10144 /*
10145  * Subtype can only access parent members with family protection if the site object
10146  * is subclass of Subtype. For example:
10147  * class A { protected int x; }
10148  * class B : A {
10149  *      void valid_access () {
10150  *              B b;
10151  *              b.x = 0;
10152  *  }
10153  *  void invalid_access () {
10154  *              A a;
10155  *              a.x = 0;
10156  *  }
10157  * }
10158  * */
10159 static gboolean
10160 is_valid_family_access (MonoClass *access_klass, MonoClass *member_klass, MonoClass *context_klass)
10161 {
10162         if (!mono_class_has_parent_and_ignore_generics (access_klass, member_klass))
10163                 return FALSE;
10164
10165         if (context_klass == NULL)
10166                 return TRUE;
10167         /*if access_klass is not member_klass context_klass must be type compat*/
10168         if (access_klass != member_klass && !mono_class_has_parent_and_ignore_generics (context_klass, access_klass))
10169                 return FALSE;
10170         return TRUE;
10171 }
10172
10173 static gboolean
10174 can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
10175 {
10176         GSList *tmp;
10177         if (accessing == accessed)
10178                 return TRUE;
10179         if (!accessed || !accessing)
10180                 return FALSE;
10181
10182         /* extra safety under CoreCLR - the runtime does not verify the strongname signatures
10183          * anywhere so untrusted friends are not safe to access platform's code internals */
10184         if (mono_security_core_clr_enabled ()) {
10185                 if (!mono_security_core_clr_can_access_internals (accessing->image, accessed->image))
10186                         return FALSE;
10187         }
10188
10189         mono_assembly_load_friends (accessed);
10190         for (tmp = accessed->friend_assembly_names; tmp; tmp = tmp->next) {
10191                 MonoAssemblyName *friend_ = (MonoAssemblyName *)tmp->data;
10192                 /* Be conservative with checks */
10193                 if (!friend_->name)
10194                         continue;
10195                 if (strcmp (accessing->aname.name, friend_->name))
10196                         continue;
10197                 if (friend_->public_key_token [0]) {
10198                         if (!accessing->aname.public_key_token [0])
10199                                 continue;
10200                         if (!mono_public_tokens_are_equal (friend_->public_key_token, accessing->aname.public_key_token))
10201                                 continue;
10202                 }
10203                 return TRUE;
10204         }
10205         return FALSE;
10206 }
10207
10208 /*
10209  * If klass is a generic type or if it is derived from a generic type, return the
10210  * MonoClass of the generic definition
10211  * Returns NULL if not found
10212  */
10213 static MonoClass*
10214 get_generic_definition_class (MonoClass *klass)
10215 {
10216         while (klass) {
10217                 if (klass->generic_class && klass->generic_class->container_class)
10218                         return klass->generic_class->container_class;
10219                 klass = klass->parent;
10220         }
10221         return NULL;
10222 }
10223
10224 static gboolean
10225 can_access_instantiation (MonoClass *access_klass, MonoGenericInst *ginst)
10226 {
10227         int i;
10228         for (i = 0; i < ginst->type_argc; ++i) {
10229                 MonoType *type = ginst->type_argv[i];
10230                 switch (type->type) {
10231                 case MONO_TYPE_SZARRAY:
10232                         if (!can_access_type (access_klass, type->data.klass))
10233                                 return FALSE;
10234                         break;
10235                 case MONO_TYPE_ARRAY:
10236                         if (!can_access_type (access_klass, type->data.array->eklass))
10237                                 return FALSE;
10238                         break;
10239                 case MONO_TYPE_PTR:
10240                         if (!can_access_type (access_klass, mono_class_from_mono_type (type->data.type)))
10241                                 return FALSE;
10242                         break;
10243                 case MONO_TYPE_CLASS:
10244                 case MONO_TYPE_VALUETYPE:
10245                 case MONO_TYPE_GENERICINST:
10246                         if (!can_access_type (access_klass, mono_class_from_mono_type (type)))
10247                                 return FALSE;
10248                 default:
10249                         break;
10250                 }
10251         }
10252         return TRUE;
10253 }
10254
10255 static gboolean
10256 can_access_type (MonoClass *access_klass, MonoClass *member_klass)
10257 {
10258         int access_level;
10259
10260         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10261                 return TRUE;
10262
10263         if (access_klass->element_class && !access_klass->enumtype)
10264                 access_klass = access_klass->element_class;
10265
10266         if (member_klass->element_class && !member_klass->enumtype)
10267                 member_klass = member_klass->element_class;
10268
10269         access_level = member_klass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK;
10270
10271         if (member_klass->byval_arg.type == MONO_TYPE_VAR || member_klass->byval_arg.type == MONO_TYPE_MVAR)
10272                 return TRUE;
10273
10274         if (member_klass->generic_class && !can_access_instantiation (access_klass, member_klass->generic_class->context.class_inst))
10275                 return FALSE;
10276
10277         if (is_nesting_type (access_klass, member_klass) || (access_klass->nested_in && is_nesting_type (access_klass->nested_in, member_klass)))
10278                 return TRUE;
10279
10280         if (member_klass->nested_in && !can_access_type (access_klass, member_klass->nested_in))
10281                 return FALSE;
10282
10283         /*Non nested type with nested visibility. We just fail it.*/
10284         if (access_level >= TYPE_ATTRIBUTE_NESTED_PRIVATE && access_level <= TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM && member_klass->nested_in == NULL)
10285                 return FALSE;
10286
10287         switch (access_level) {
10288         case TYPE_ATTRIBUTE_NOT_PUBLIC:
10289                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10290
10291         case TYPE_ATTRIBUTE_PUBLIC:
10292                 return TRUE;
10293
10294         case TYPE_ATTRIBUTE_NESTED_PUBLIC:
10295                 return TRUE;
10296
10297         case TYPE_ATTRIBUTE_NESTED_PRIVATE:
10298                 return is_nesting_type (member_klass, access_klass);
10299
10300         case TYPE_ATTRIBUTE_NESTED_FAMILY:
10301                 return mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in); 
10302
10303         case TYPE_ATTRIBUTE_NESTED_ASSEMBLY:
10304                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10305
10306         case TYPE_ATTRIBUTE_NESTED_FAM_AND_ASSEM:
10307                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) &&
10308                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10309
10310         case TYPE_ATTRIBUTE_NESTED_FAM_OR_ASSEM:
10311                 return can_access_internals (access_klass->image->assembly, member_klass->nested_in->image->assembly) ||
10312                         mono_class_has_parent_and_ignore_generics (access_klass, member_klass->nested_in);
10313         }
10314         return FALSE;
10315 }
10316
10317 /* FIXME: check visibility of type, too */
10318 static gboolean
10319 can_access_member (MonoClass *access_klass, MonoClass *member_klass, MonoClass* context_klass, int access_level)
10320 {
10321         MonoClass *member_generic_def;
10322         if (access_klass->image->assembly && access_klass->image->assembly->corlib_internal)
10323                 return TRUE;
10324
10325         if (((access_klass->generic_class && access_klass->generic_class->container_class) ||
10326                                         access_klass->generic_container) && 
10327                         (member_generic_def = get_generic_definition_class (member_klass))) {
10328                 MonoClass *access_container;
10329
10330                 if (access_klass->generic_container)
10331                         access_container = access_klass;
10332                 else
10333                         access_container = access_klass->generic_class->container_class;
10334
10335                 if (can_access_member (access_container, member_generic_def, context_klass, access_level))
10336                         return TRUE;
10337         }
10338
10339         /* Partition I 8.5.3.2 */
10340         /* the access level values are the same for fields and methods */
10341         switch (access_level) {
10342         case FIELD_ATTRIBUTE_COMPILER_CONTROLLED:
10343                 /* same compilation unit */
10344                 return access_klass->image == member_klass->image;
10345         case FIELD_ATTRIBUTE_PRIVATE:
10346                 return access_klass == member_klass;
10347         case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
10348                 if (is_valid_family_access (access_klass, member_klass, context_klass) &&
10349                     can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
10350                         return TRUE;
10351                 return FALSE;
10352         case FIELD_ATTRIBUTE_ASSEMBLY:
10353                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10354         case FIELD_ATTRIBUTE_FAMILY:
10355                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10356                         return TRUE;
10357                 return FALSE;
10358         case FIELD_ATTRIBUTE_FAM_OR_ASSEM:
10359                 if (is_valid_family_access (access_klass, member_klass, context_klass))
10360                         return TRUE;
10361                 return can_access_internals (access_klass->image->assembly, member_klass->image->assembly);
10362         case FIELD_ATTRIBUTE_PUBLIC:
10363                 return TRUE;
10364         }
10365         return FALSE;
10366 }
10367
10368 /**
10369  * mono_method_can_access_field:
10370  * @method: Method that will attempt to access the field
10371  * @field: the field to access
10372  *
10373  * Used to determine if a method is allowed to access the specified field.
10374  *
10375  * Returns: TRUE if the given @method is allowed to access the @field while following
10376  * the accessibility rules of the CLI.
10377  */
10378 gboolean
10379 mono_method_can_access_field (MonoMethod *method, MonoClassField *field)
10380 {
10381         /* FIXME: check all overlapping fields */
10382         int can = can_access_member (method->klass, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10383         if (!can) {
10384                 MonoClass *nested = method->klass->nested_in;
10385                 while (nested) {
10386                         can = can_access_member (nested, field->parent, NULL, mono_field_get_type (field)->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10387                         if (can)
10388                                 return TRUE;
10389                         nested = nested->nested_in;
10390                 }
10391         }
10392         return can;
10393 }
10394
10395 /**
10396  * mono_method_can_access_method:
10397  * @method: Method that will attempt to access the other method
10398  * @called: the method that we want to probe for accessibility.
10399  *
10400  * Used to determine if the @method is allowed to access the specified @called method.
10401  *
10402  * Returns: TRUE if the given @method is allowed to invoke the @called while following
10403  * the accessibility rules of the CLI.
10404  */
10405 gboolean
10406 mono_method_can_access_method (MonoMethod *method, MonoMethod *called)
10407 {
10408         int can = can_access_member (method->klass, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10409         if (!can) {
10410                 MonoClass *nested = method->klass->nested_in;
10411                 while (nested) {
10412                         can = can_access_member (nested, called->klass, NULL, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10413                         if (can)
10414                                 return TRUE;
10415                         nested = nested->nested_in;
10416                 }
10417         }
10418         /* 
10419          * FIXME:
10420          * with generics calls to explicit interface implementations can be expressed
10421          * directly: the method is private, but we must allow it. This may be opening
10422          * a hole or the generics code should handle this differently.
10423          * Maybe just ensure the interface type is public.
10424          */
10425         if ((called->flags & METHOD_ATTRIBUTE_VIRTUAL) && (called->flags & METHOD_ATTRIBUTE_FINAL))
10426                 return TRUE;
10427         return can;
10428 }
10429
10430 /*
10431  * mono_method_can_access_method_full:
10432  * @method: The caller method 
10433  * @called: The called method 
10434  * @context_klass: The static type on stack of the owner @called object used
10435  * 
10436  * This function must be used with instance calls, as they have more strict family accessibility.
10437  * It can be used with static methods, but context_klass should be NULL.
10438  * 
10439  * Returns: TRUE if caller have proper visibility and acessibility to @called
10440  */
10441 gboolean
10442 mono_method_can_access_method_full (MonoMethod *method, MonoMethod *called, MonoClass *context_klass)
10443 {
10444         MonoClass *access_class = method->klass;
10445         MonoClass *member_class = called->klass;
10446         int can = can_access_member (access_class, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10447         if (!can) {
10448                 MonoClass *nested = access_class->nested_in;
10449                 while (nested) {
10450                         can = can_access_member (nested, member_class, context_klass, called->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK);
10451                         if (can)
10452                                 break;
10453                         nested = nested->nested_in;
10454                 }
10455         }
10456
10457         if (!can)
10458                 return FALSE;
10459
10460         can = can_access_type (access_class, member_class);
10461         if (!can) {
10462                 MonoClass *nested = access_class->nested_in;
10463                 while (nested) {
10464                         can = can_access_type (nested, member_class);
10465                         if (can)
10466                                 break;
10467                         nested = nested->nested_in;
10468                 }
10469         }
10470
10471         if (!can)
10472                 return FALSE;
10473
10474         if (called->is_inflated) {
10475                 MonoMethodInflated * infl = (MonoMethodInflated*)called;
10476                 if (infl->context.method_inst && !can_access_instantiation (access_class, infl->context.method_inst))
10477                         return FALSE;
10478         }
10479                 
10480         return TRUE;
10481 }
10482
10483
10484 /*
10485  * mono_method_can_access_field_full:
10486  * @method: The caller method 
10487  * @field: The accessed field
10488  * @context_klass: The static type on stack of the owner @field object used
10489  * 
10490  * This function must be used with instance fields, as they have more strict family accessibility.
10491  * It can be used with static fields, but context_klass should be NULL.
10492  * 
10493  * Returns: TRUE if caller have proper visibility and acessibility to @field
10494  */
10495 gboolean
10496 mono_method_can_access_field_full (MonoMethod *method, MonoClassField *field, MonoClass *context_klass)
10497 {
10498         MonoClass *access_class = method->klass;
10499         MonoClass *member_class = field->parent;
10500         /* FIXME: check all overlapping fields */
10501         int can = can_access_member (access_class, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10502         if (!can) {
10503                 MonoClass *nested = access_class->nested_in;
10504                 while (nested) {
10505                         can = can_access_member (nested, member_class, context_klass, field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK);
10506                         if (can)
10507                                 break;
10508                         nested = nested->nested_in;
10509                 }
10510         }
10511
10512         if (!can)
10513                 return FALSE;
10514
10515         can = can_access_type (access_class, member_class);
10516         if (!can) {
10517                 MonoClass *nested = access_class->nested_in;
10518                 while (nested) {
10519                         can = can_access_type (nested, member_class);
10520                         if (can)
10521                                 break;
10522                         nested = nested->nested_in;
10523                 }
10524         }
10525
10526         if (!can)
10527                 return FALSE;
10528         return TRUE;
10529 }
10530
10531 /*
10532  * mono_class_can_access_class:
10533  * @source_class: The source class 
10534  * @target_class: The accessed class
10535  * 
10536  * This function returns is @target_class is visible to @source_class
10537  * 
10538  * Returns: TRUE if source have proper visibility and acessibility to target
10539  */
10540 gboolean
10541 mono_class_can_access_class (MonoClass *source_class, MonoClass *target_class)
10542 {
10543         return can_access_type (source_class, target_class);
10544 }
10545
10546 /**
10547  * mono_type_is_valid_enum_basetype:
10548  * @type: The MonoType to check
10549  *
10550  * Returns: TRUE if the type can be used as the basetype of an enum
10551  */
10552 gboolean mono_type_is_valid_enum_basetype (MonoType * type) {
10553         switch (type->type) {
10554         case MONO_TYPE_I1:
10555         case MONO_TYPE_U1:
10556         case MONO_TYPE_BOOLEAN:
10557         case MONO_TYPE_I2:
10558         case MONO_TYPE_U2:
10559         case MONO_TYPE_CHAR:
10560         case MONO_TYPE_I4:
10561         case MONO_TYPE_U4:
10562         case MONO_TYPE_I8:
10563         case MONO_TYPE_U8:
10564         case MONO_TYPE_I:
10565         case MONO_TYPE_U:
10566                 return TRUE;
10567         default:
10568                 return FALSE;
10569         }
10570 }
10571
10572 /**
10573  * mono_class_is_valid_enum:
10574  * @klass: An enum class to be validated
10575  *
10576  * This method verify the required properties an enum should have.
10577  *  
10578  * Returns: TRUE if the informed enum class is valid 
10579  *
10580  * FIXME: TypeBuilder enums are allowed to implement interfaces, but since they cannot have methods, only empty interfaces are possible
10581  * FIXME: enum types are not allowed to have a cctor, but mono_reflection_create_runtime_class sets has_cctor to 1 for all types
10582  * FIXME: TypeBuilder enums can have any kind of static fields, but the spec is very explicit about that (P II 14.3)
10583  */
10584 gboolean mono_class_is_valid_enum (MonoClass *klass) {
10585         MonoClassField * field;
10586         gpointer iter = NULL;
10587         gboolean found_base_field = FALSE;
10588
10589         g_assert (klass->enumtype);
10590         /* we cannot test against mono_defaults.enum_class, or mcs won't be able to compile the System namespace*/
10591         if (!klass->parent || strcmp (klass->parent->name, "Enum") || strcmp (klass->parent->name_space, "System") ) {
10592                 return FALSE;
10593         }
10594
10595         if ((klass->flags & TYPE_ATTRIBUTE_LAYOUT_MASK) != TYPE_ATTRIBUTE_AUTO_LAYOUT)
10596                 return FALSE;
10597
10598         while ((field = mono_class_get_fields (klass, &iter))) {
10599                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
10600                         if (found_base_field)
10601                                 return FALSE;
10602                         found_base_field = TRUE;
10603                         if (!mono_type_is_valid_enum_basetype (field->type))
10604                                 return FALSE;
10605                 }
10606         }
10607
10608         if (!found_base_field)
10609                 return FALSE;
10610
10611         if (klass->method.count > 0) 
10612                 return FALSE;
10613
10614         return TRUE;
10615 }
10616
10617 gboolean
10618 mono_generic_class_is_generic_type_definition (MonoGenericClass *gklass)
10619 {
10620         return gklass->context.class_inst == gklass->container_class->generic_container->context.class_inst;
10621 }
10622
10623 /*
10624  * mono_class_setup_interface_id:
10625  *
10626  * Initializes MonoClass::interface_id if required.
10627  *
10628  * LOCKING: Acquires the loader lock.
10629  */
10630 void
10631 mono_class_setup_interface_id (MonoClass *klass)
10632 {
10633         mono_loader_lock ();
10634         if (MONO_CLASS_IS_INTERFACE (klass) && !klass->interface_id)
10635                 klass->interface_id = mono_get_unique_iid (klass);
10636         mono_loader_unlock ();
10637 }
10638
10639 /*
10640  * mono_class_alloc_ext:
10641  *
10642  *   Allocate klass->ext if not already done.
10643  */
10644 void
10645 mono_class_alloc_ext (MonoClass *klass)
10646 {
10647         MonoClassExt *ext;
10648
10649         if (klass->ext)
10650                 return;
10651
10652         ext = (MonoClassExt *)mono_class_alloc0 (klass, sizeof (MonoClassExt));
10653         mono_image_lock (klass->image);
10654         mono_memory_barrier ();
10655         if (!klass->ext)
10656                 klass->ext = ext;
10657         class_ext_size += sizeof (MonoClassExt);
10658         mono_image_unlock (klass->image);
10659 }
10660
10661 /*
10662  * mono_class_setup_interfaces:
10663  *
10664  *   Initialize klass->interfaces/interfaces_count.
10665  * LOCKING: Acquires the loader lock.
10666  * This function can fail the type.
10667  */
10668 void
10669 mono_class_setup_interfaces (MonoClass *klass, MonoError *error)
10670 {
10671         int i, interface_count;
10672         MonoClass **interfaces;
10673
10674         mono_error_init (error);
10675
10676         if (klass->interfaces_inited)
10677                 return;
10678
10679         if (klass->rank == 1 && klass->byval_arg.type != MONO_TYPE_ARRAY) {
10680                 MonoType *args [1];
10681
10682                 /* generic IList, ICollection, IEnumerable */
10683                 interface_count = mono_defaults.generic_ireadonlylist_class ? 2 : 1;
10684                 interfaces = (MonoClass **)mono_image_alloc0 (klass->image, sizeof (MonoClass*) * interface_count);
10685
10686                 args [0] = &klass->element_class->byval_arg;
10687                 interfaces [0] = mono_class_bind_generic_parameters (
10688                         mono_defaults.generic_ilist_class, 1, args, FALSE);
10689                 if (interface_count > 1)
10690                         interfaces [1] = mono_class_bind_generic_parameters (
10691                            mono_defaults.generic_ireadonlylist_class, 1, args, FALSE);
10692         } else if (klass->generic_class) {
10693                 MonoClass *gklass = klass->generic_class->container_class;
10694
10695                 mono_class_setup_interfaces (gklass, error);
10696                 if (!mono_error_ok (error)) {
10697                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10698                         return;
10699                 }
10700
10701                 interface_count = gklass->interface_count;
10702                 interfaces = mono_class_new0 (klass, MonoClass *, interface_count);
10703                 for (i = 0; i < interface_count; i++) {
10704                         interfaces [i] = mono_class_inflate_generic_class_checked (gklass->interfaces [i], mono_generic_class_get_context (klass->generic_class), error);
10705                         if (!mono_error_ok (error)) {
10706                                 mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup ("Could not setup the interfaces"));
10707                                 return;
10708                         }
10709                 }
10710         } else {
10711                 interface_count = 0;
10712                 interfaces = NULL;
10713         }
10714
10715         mono_image_lock (klass->image);
10716
10717         if (!klass->interfaces_inited) {
10718                 klass->interface_count = interface_count;
10719                 klass->interfaces = interfaces;
10720
10721                 mono_memory_barrier ();
10722
10723                 klass->interfaces_inited = TRUE;
10724         }
10725
10726         mono_image_unlock (klass->image);
10727 }
10728
10729 static void
10730 mono_field_resolve_type (MonoClassField *field, MonoError *error)
10731 {
10732         MonoClass *klass = field->parent;
10733         MonoImage *image = klass->image;
10734         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10735         int field_idx = field - klass->fields;
10736
10737         mono_error_init (error);
10738
10739         if (gtd) {
10740                 MonoClassField *gfield = &gtd->fields [field_idx];
10741                 MonoType *gtype = mono_field_get_type_checked (gfield, error);
10742                 if (!mono_error_ok (error)) {
10743                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10744                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10745                 }
10746
10747                 field->type = mono_class_inflate_generic_type_no_copy (image, gtype, mono_class_get_context (klass), error);
10748                 if (!mono_error_ok (error)) {
10749                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10750                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10751                 }
10752         } else {
10753                 const char *sig;
10754                 guint32 cols [MONO_FIELD_SIZE];
10755                 MonoGenericContainer *container = NULL;
10756                 int idx = klass->field.first + field_idx;
10757
10758                 /*FIXME, in theory we do not lazy load SRE fields*/
10759                 g_assert (!image_is_dynamic (image));
10760
10761                 if (klass->generic_container) {
10762                         container = klass->generic_container;
10763                 } else if (gtd) {
10764                         container = gtd->generic_container;
10765                         g_assert (container);
10766                 }
10767
10768                 /* klass->field.first and idx points into the fieldptr table */
10769                 mono_metadata_decode_table_row (image, MONO_TABLE_FIELD, idx, cols, MONO_FIELD_SIZE);
10770
10771                 if (!mono_verifier_verify_field_signature (image, cols [MONO_FIELD_SIGNATURE], NULL)) {
10772                         mono_error_set_type_load_class (error, klass, "Could not verify field %s signature", field->name);;
10773                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, g_strdup (mono_error_get_message (error)));
10774                         return;
10775                 }
10776
10777                 sig = mono_metadata_blob_heap (image, cols [MONO_FIELD_SIGNATURE]);
10778
10779                 mono_metadata_decode_value (sig, &sig);
10780                 /* FIELD signature == 0x06 */
10781                 g_assert (*sig == 0x06);
10782
10783                 field->type = mono_metadata_parse_type_checked (image, container, cols [MONO_FIELD_FLAGS], FALSE, sig + 1, &sig, error);
10784                 if (!field->type) {
10785                         char *err_msg = g_strdup_printf ("Could not load field %d type due to: %s", field_idx, mono_error_get_message (error));
10786                         mono_class_set_failure (klass, MONO_EXCEPTION_TYPE_LOAD, err_msg);
10787                 }
10788         }
10789 }
10790
10791 static guint32
10792 mono_field_resolve_flags (MonoClassField *field)
10793 {
10794         MonoClass *klass = field->parent;
10795         MonoImage *image = klass->image;
10796         MonoClass *gtd = klass->generic_class ? mono_class_get_generic_type_definition (klass) : NULL;
10797         int field_idx = field - klass->fields;
10798
10799
10800         if (gtd) {
10801                 MonoClassField *gfield = &gtd->fields [field_idx];
10802                 return mono_field_get_flags (gfield);
10803         } else {
10804                 int idx = klass->field.first + field_idx;
10805
10806                 /*FIXME, in theory we do not lazy load SRE fields*/
10807                 g_assert (!image_is_dynamic (image));
10808
10809                 return mono_metadata_decode_table_row_col (image, MONO_TABLE_FIELD, idx, MONO_FIELD_FLAGS);
10810         }
10811 }
10812
10813 /**
10814  * mono_class_setup_basic_field_info:
10815  * @class: The class to initialize
10816  *
10817  * Initializes the klass->fields array of fields.
10818  * Aquires the loader lock.
10819  */
10820 static void
10821 mono_class_setup_basic_field_info_locking (MonoClass *klass)
10822 {
10823         mono_loader_lock ();
10824         mono_class_setup_basic_field_info (klass);
10825         mono_loader_unlock ();
10826 }
10827
10828 /**
10829  * mono_class_get_fields_lazy:
10830  * @klass: the MonoClass to act on
10831  *
10832  * This routine is an iterator routine for retrieving the fields in a class.
10833  * Only minimal information about fields are loaded. Accessors must be used
10834  * for all MonoClassField returned.
10835  *
10836  * You must pass a gpointer that points to zero and is treated as an opaque handle to
10837  * iterate over all of the elements.  When no more values are
10838  * available, the return value is NULL.
10839  *
10840  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
10841  */
10842 MonoClassField*
10843 mono_class_get_fields_lazy (MonoClass* klass, gpointer *iter)
10844 {
10845         MonoClassField* field;
10846         if (!iter)
10847                 return NULL;
10848         if (!*iter) {
10849                 mono_class_setup_basic_field_info_locking (klass);
10850                 if (!klass->fields)
10851                         return NULL;
10852                 /* start from the first */
10853                 if (klass->field.count) {
10854                         *iter = &klass->fields [0];
10855                         return (MonoClassField *)*iter;
10856                 } else {
10857                         /* no fields */
10858                         return NULL;
10859                 }
10860         }
10861         field = (MonoClassField *)*iter;
10862         field++;
10863         if (field < &klass->fields [klass->field.count]) {
10864                 *iter = field;
10865                 return (MonoClassField *)*iter;
10866         }
10867         return NULL;
10868 }
10869
10870 char*
10871 mono_class_full_name (MonoClass *klass)
10872 {
10873         return mono_type_full_name (&klass->byval_arg);
10874 }
10875
10876 /* Declare all shared lazy type lookup functions */
10877 GENERATE_TRY_GET_CLASS_WITH_CACHE (safehandle, System.Runtime.InteropServices, SafeHandle)