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