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