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