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