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