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