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