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