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