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