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