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