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