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