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