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