aec749bd499416a18f95fc8dda2e789a98e70dd1
[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 Ximian, Inc.
8  *
9  * Possible Optimizations:
10  *     in mono_class_create, do not allocate the class right away,
11  *     but wait until you know the size of the FieldMap, so that
12  *     the class embeds directly the FieldMap after the vtable.
13  *
14  * 
15  */
16 #include <config.h>
17 #include <glib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #include <signal.h>
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/assembly.h>
24 #include <mono/metadata/cil-coff.h>
25 #include <mono/metadata/metadata.h>
26 #include <mono/metadata/metadata-internals.h>
27 #include <mono/metadata/tabledefs.h>
28 #include <mono/metadata/tokentype.h>
29 #include <mono/metadata/class-internals.h>
30 #include <mono/metadata/object.h>
31 #include <mono/metadata/appdomain.h>
32 #include <mono/metadata/mono-endian.h>
33 #include <mono/metadata/debug-helpers.h>
34 #include <mono/metadata/reflection.h>
35 #include <mono/metadata/exception.h>
36 #include <mono/metadata/security-manager.h>
37 #include <mono/os/gc_wrapper.h>
38
39 MonoStats mono_stats;
40
41 gboolean mono_print_vtable = FALSE;
42
43 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
44 static void mono_class_create_generic (MonoInflatedGenericClass *gclass);
45 static gboolean mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res);
46
47 void (*mono_debugger_start_class_init_func) (MonoClass *klass) = NULL;
48 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
49
50 MonoClass *
51 mono_class_from_typeref (MonoImage *image, guint32 type_token)
52 {
53         guint32 cols [MONO_TYPEREF_SIZE];
54         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
55         guint32 idx;
56         const char *name, *nspace;
57         MonoClass *res;
58         MonoAssembly **references;
59         
60         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
61
62         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
63         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
64
65         idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
66         switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
67         case MONO_RESOLTION_SCOPE_MODULE:
68                 if (!idx)
69                         g_error ("null ResolutionScope not yet handled");
70                 /* a typedef in disguise */
71                 return mono_class_from_name (image, nspace, name);
72         case MONO_RESOLTION_SCOPE_MODULEREF:
73                 return mono_class_from_name (image->modules [idx - 1], nspace, name);
74         case MONO_RESOLTION_SCOPE_TYPEREF: {
75                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
76                 GList *tmp;
77
78                 if (enclosing->inited) {
79                         /* Micro-optimization: don't scan the metadata tables if enclosing is already inited */
80                         for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
81                                 res = tmp->data;
82                                 if (strcmp (res->name, name) == 0)
83                                         return res;
84                         }
85                 } else {
86                         /* Don't call mono_class_init as we might've been called by it recursively */
87                         int i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, 1);
88                         while (i) {
89                                 guint32 class_nested = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, MONO_NESTED_CLASS_NESTED);
90                                 guint32 string_offset = mono_metadata_decode_row_col (&enclosing->image->tables [MONO_TABLE_TYPEDEF], class_nested - 1, MONO_TYPEDEF_NAME);
91                                 const char *nname = mono_metadata_string_heap (enclosing->image, string_offset);
92
93                                 if (strcmp (nname, name) == 0)
94                                         return mono_class_create_from_typedef (enclosing->image, MONO_TOKEN_TYPE_DEF | class_nested);
95
96                                 i = mono_metadata_nesting_typedef (enclosing->image, enclosing->type_token, i + 1);
97                         }
98                 }
99                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
100                 return NULL;
101         }
102         case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
103                 break;
104         }
105
106         references = image->references;
107         if (!references [idx - 1])
108                 mono_assembly_load_reference (image, idx - 1);
109         /* If this assert fails, it probably means that you haven't installed an assembly load/search hook */
110         g_assert (references == image->references);
111         g_assert (references [idx - 1]);
112         if (references [idx - 1] == (gpointer)-1)
113                 return NULL;
114
115         return mono_class_from_name (references [idx - 1]->image, nspace, name);
116 }
117
118 static inline MonoType*
119 dup_type (MonoType* t, const MonoType *original)
120 {
121         MonoType *r = g_new0 (MonoType, 1);
122         *r = *t;
123         r->attrs = original->attrs;
124         r->byref = original->byref;
125         if (t->type == MONO_TYPE_PTR)
126                 t->data.type = dup_type (t->data.type, original->data.type);
127         else if (t->type == MONO_TYPE_ARRAY)
128                 t->data.array = mono_dup_array_type (t->data.array);
129         else if (t->type == MONO_TYPE_FNPTR)
130                 t->data.method = mono_metadata_signature_deep_dup (t->data.method);
131         mono_stats.generics_metadata_size += sizeof (MonoType);
132         return r;
133 }
134
135 /* Copy everything mono_metadata_free_array free. */
136 MonoArrayType *
137 mono_dup_array_type (MonoArrayType *a)
138 {
139         a = g_memdup (a, sizeof (MonoArrayType));
140         if (a->sizes)
141                 a->sizes = g_memdup (a->sizes, a->numsizes * sizeof (int));
142         if (a->lobounds)
143                 a->lobounds = g_memdup (a->lobounds, a->numlobounds * sizeof (int));
144         return a;
145 }
146
147 /* Copy everything mono_metadata_free_method_signature free. */
148 MonoMethodSignature*
149 mono_metadata_signature_deep_dup (MonoMethodSignature *sig)
150 {
151         int i;
152         
153         sig = mono_metadata_signature_dup (sig);
154         
155         sig->ret = dup_type (sig->ret, sig->ret);
156         for (i = 0; i < sig->param_count; ++i)
157                 sig->params [i] = dup_type (sig->params [i], sig->params [i]);
158         
159         return sig;
160 }
161
162 static void
163 _mono_type_get_assembly_name (MonoClass *klass, GString *str)
164 {
165         MonoAssembly *ta = klass->image->assembly;
166
167         g_string_append_printf (
168                 str, ", %s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s",
169                 ta->aname.name,
170                 ta->aname.major, ta->aname.minor, ta->aname.build, ta->aname.revision,
171                 ta->aname.culture && *ta->aname.culture? ta->aname.culture: "neutral",
172                 ta->aname.public_key_token [0] ? (char *)ta->aname.public_key_token : "null");
173 }
174
175 static void
176 mono_type_get_name_recurse (MonoType *type, GString *str, gboolean is_recursed,
177                             MonoTypeNameFormat format)
178 {
179         MonoClass *klass;
180         
181         switch (type->type) {
182         case MONO_TYPE_ARRAY: {
183                 int i, rank = type->data.array->rank;
184                 MonoTypeNameFormat nested_format;
185
186                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
187                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
188
189                 mono_type_get_name_recurse (
190                         &type->data.array->eklass->byval_arg, str, FALSE, nested_format);
191                 g_string_append_c (str, '[');
192                 for (i = 1; i < rank; i++)
193                         g_string_append_c (str, ',');
194                 g_string_append_c (str, ']');
195                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
196                         _mono_type_get_assembly_name (type->data.array->eklass, str);
197                 break;
198         }
199         case MONO_TYPE_SZARRAY: {
200                 MonoTypeNameFormat nested_format;
201
202                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
203                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
204
205                 mono_type_get_name_recurse (
206                         &type->data.klass->byval_arg, str, FALSE, nested_format);
207                 g_string_append (str, "[]");
208                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
209                         _mono_type_get_assembly_name (type->data.klass, str);
210                 break;
211         }
212         case MONO_TYPE_PTR: {
213                 MonoTypeNameFormat nested_format;
214
215                 nested_format = format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED ?
216                         MONO_TYPE_NAME_FORMAT_FULL_NAME : format;
217
218                 mono_type_get_name_recurse (
219                         type->data.type, str, FALSE, nested_format);
220                 g_string_append (str, "*");
221                 if (format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)
222                         _mono_type_get_assembly_name (type->data.klass, str);
223                 break;
224         }
225         case MONO_TYPE_VAR:
226         case MONO_TYPE_MVAR:
227                 g_assert (type->data.generic_param->name);
228                 g_string_append (str, type->data.generic_param->name);
229                 break;
230         default:
231                 klass = mono_class_from_mono_type (type);
232                 if (klass->nested_in) {
233                         mono_type_get_name_recurse (
234                                 &klass->nested_in->byval_arg, str, TRUE, format);
235                         if (format == MONO_TYPE_NAME_FORMAT_IL)
236                                 g_string_append_c (str, '.');
237                         else
238                                 g_string_append_c (str, '+');
239                 } else if (*klass->name_space) {
240                         g_string_append (str, klass->name_space);
241                         g_string_append_c (str, '.');
242                 }
243                 if (format == MONO_TYPE_NAME_FORMAT_IL) {
244                         char *s = strchr (klass->name, '`');
245                         int len = s ? s - klass->name : strlen (klass->name);
246
247                         g_string_append_len (str, klass->name, len);
248                 } else
249                         g_string_append (str, klass->name);
250                 if (is_recursed)
251                         break;
252                 if (klass->generic_class) {
253                         MonoGenericClass *gclass = klass->generic_class;
254                         MonoTypeNameFormat nested_format;
255                         int i;
256
257                         nested_format = format == MONO_TYPE_NAME_FORMAT_FULL_NAME ?
258                                 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED : format;
259
260                         if (format == MONO_TYPE_NAME_FORMAT_IL)
261                                 g_string_append_c (str, '<');
262                         else
263                                 g_string_append_c (str, '[');
264                         for (i = 0; i < gclass->inst->type_argc; i++) {
265                                 MonoType *t = gclass->inst->type_argv [i];
266
267                                 if (i)
268                                         g_string_append_c (str, ',');
269                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
270                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
271                                         g_string_append_c (str, '[');
272                                 mono_type_get_name_recurse (
273                                         gclass->inst->type_argv [i], str, FALSE, nested_format);
274                                 if ((nested_format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
275                                     (t->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
276                                         g_string_append_c (str, ']');
277                         }
278                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
279                                 g_string_append_c (str, '>');
280                         else
281                                 g_string_append_c (str, ']');
282                 } else if (klass->generic_container &&
283                            (format != MONO_TYPE_NAME_FORMAT_FULL_NAME) &&
284                            (format != MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED)) {
285                         int i;
286
287                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
288                                 g_string_append_c (str, '<');
289                         else
290                                 g_string_append_c (str, '[');
291                         for (i = 0; i < klass->generic_container->type_argc; i++) {
292                                 if (i)
293                                         g_string_append_c (str, ',');
294                                 g_string_append (str, klass->generic_container->type_params [i].name);
295                         }
296                         if (format == MONO_TYPE_NAME_FORMAT_IL) 
297                                 g_string_append_c (str, '>');
298                         else
299                                 g_string_append_c (str, ']');
300                 }
301                 if ((format == MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED) &&
302                     (type->type != MONO_TYPE_VAR) && (type->type != MONO_TYPE_MVAR))
303                         _mono_type_get_assembly_name (klass, str);
304                 break;
305         }
306 }
307
308 /**
309  * mono_type_get_name:
310  * @type: a type
311  * @format: the format for the return string.
312  *
313  * 
314  * Returns: the string representation in a number of formats:
315  *
316  * if format is MONO_TYPE_NAME_FORMAT_REFLECTION, the return string is
317  * returned in the formatrequired by System.Reflection, this is the
318  * inverse of mono_reflection_parse_type ().
319  *
320  * if format is MONO_TYPE_NAME_FORMAT_IL, it returns a syntax that can
321  * be used by the IL assembler.
322  *
323  * if format is MONO_TYPE_NAME_FORMAT_FULL_NAME
324  *
325  * if format is MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED
326  */
327 char*
328 mono_type_get_name_full (MonoType *type, MonoTypeNameFormat format)
329 {
330         GString* result;
331
332         result = g_string_new ("");
333
334         mono_type_get_name_recurse (type, result, FALSE, format);
335
336         if (type->byref)
337                 g_string_append_c (result, '&');
338
339         return g_string_free (result, FALSE);
340 }
341
342 /**
343  * mono_type_get_full_name:
344  * @class: a class
345  *
346  * Returns: the string representation for type as required by System.Reflection.
347  * The inverse of mono_reflection_parse_type ().
348  */
349 char *
350 mono_type_get_full_name (MonoClass *class)
351 {
352         return mono_type_get_name_full (mono_class_get_type (class), MONO_TYPE_NAME_FORMAT_REFLECTION);
353 }
354
355 char*
356 mono_type_get_name (MonoType *type)
357 {
358         return mono_type_get_name_full (type, MONO_TYPE_NAME_FORMAT_IL);
359 }
360
361 /*
362  * mono_type_get_underlying_type:
363  * @type: a type
364  *
365  * Returns: the MonoType for the underlying interger type if @type
366  * is an enum, otherwise the type itself.
367  */
368 MonoType*
369 mono_type_get_underlying_type (MonoType *type)
370 {
371         if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
372                 return type->data.klass->enum_basetype;
373         return type;
374 }
375
376 gboolean
377 mono_class_is_open_constructed_type (MonoType *t)
378 {
379         switch (t->type) {
380         case MONO_TYPE_VAR:
381         case MONO_TYPE_MVAR:
382                 return TRUE;
383         case MONO_TYPE_SZARRAY:
384                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
385         case MONO_TYPE_ARRAY:
386                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
387         case MONO_TYPE_PTR:
388                 return mono_class_is_open_constructed_type (t->data.type);
389         case MONO_TYPE_GENERICINST: {
390                 MonoGenericClass *gclass = t->data.generic_class;
391                 int i;
392
393                 if (mono_class_is_open_constructed_type (&gclass->container_class->byval_arg))
394                         return TRUE;
395                 for (i = 0; i < gclass->inst->type_argc; i++)
396                         if (mono_class_is_open_constructed_type (gclass->inst->type_argv [i]))
397                                 return TRUE;
398                 return FALSE;
399         }
400         default:
401                 return FALSE;
402         }
403 }
404
405 static MonoGenericClass *
406 inflate_generic_class (MonoGenericClass *ogclass, MonoGenericContext *context)
407 {
408         MonoInflatedGenericClass *igclass;
409         MonoGenericClass *ngclass, *cached;
410         MonoGenericInst *ninst;
411
412         ninst = mono_metadata_inflate_generic_inst (ogclass->inst, context);
413         if (ninst == ogclass->inst)
414                 return ogclass;
415
416         if (ogclass->is_dynamic) {
417                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
418                 igclass = &dgclass->generic_class;
419                 ngclass = &igclass->generic_class;
420                 ngclass->is_inflated = 1;
421                 ngclass->is_dynamic = 1;
422         } else {
423                 igclass = g_new0 (MonoInflatedGenericClass, 1);
424                 ngclass = &igclass->generic_class;
425                 ngclass->is_inflated = 1;
426         }
427
428         *ngclass = *ogclass;
429
430         ngclass->inst = ninst;
431
432         igclass->klass = NULL;
433
434         ngclass->context = g_new0 (MonoGenericContext, 1);
435         ngclass->context->container = ngclass->container_class->generic_container;
436         ngclass->context->gclass = ngclass;
437
438         mono_loader_lock ();
439         cached = mono_metadata_lookup_generic_class (ngclass);
440         mono_loader_unlock ();
441         if (cached) {
442                 g_free (ngclass->context);
443                 g_free (ngclass);
444                 return cached;
445         }
446
447         return ngclass;
448 }
449
450 static MonoType*
451 inflate_generic_type (MonoType *type, MonoGenericContext *context)
452 {
453         switch (type->type) {
454         case MONO_TYPE_MVAR: {
455                 int num = type->data.generic_param->num;
456                 MonoGenericInst *inst = context->gmethod ? context->gmethod->inst : NULL;
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                 return dup_type (inst->type_argv [num], type);
462         }
463         case MONO_TYPE_VAR: {
464                 int num = type->data.generic_param->num;
465                 MonoGenericInst *inst = context->gclass ? context->gclass->inst : NULL;
466                 if (!inst)
467                         return NULL;
468                 if (num >= inst->type_argc)
469                         g_error ("VAR %d (%s) cannot be expanded in this context with %d instantiations", num, type->data.generic_param->name, inst->type_argc);
470                 return dup_type (inst->type_argv [num], type);
471         }
472         case MONO_TYPE_SZARRAY: {
473                 MonoClass *eclass = type->data.klass;
474                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
475                 if (!inflated)
476                         return NULL;
477                 nt = dup_type (type, type);
478                 nt->data.klass = mono_class_from_mono_type (inflated);
479                 return nt;
480         }
481         case MONO_TYPE_ARRAY: {
482                 MonoClass *eclass = type->data.array->eklass;
483                 MonoType *nt, *inflated = inflate_generic_type (&eclass->byval_arg, context);
484                 if (!inflated)
485                         return NULL;
486                 nt = dup_type (type, type);
487                 nt->data.array = g_memdup (nt->data.array, sizeof (MonoArrayType));
488                 nt->data.array->eklass = mono_class_from_mono_type (inflated);
489                 return nt;
490         }
491         case MONO_TYPE_GENERICINST: {
492                 MonoGenericClass *gclass = type->data.generic_class;
493                 MonoType *nt;
494                 if (!gclass->inst->is_open)
495                         return NULL;
496                 gclass = inflate_generic_class (gclass, context);
497                 if (gclass == type->data.generic_class)
498                         return NULL;
499                 nt = dup_type (type, type);
500                 nt->data.generic_class = gclass;
501                 return nt;
502         }
503         case MONO_TYPE_CLASS:
504         case MONO_TYPE_VALUETYPE: {
505                 MonoClass *klass = type->data.klass;
506                 MonoGenericClass *gclass;
507                 MonoType *nt;
508
509                 if (!klass->generic_container)
510                         return NULL;
511                 gclass = inflate_generic_class (klass->generic_container->context.gclass, context);
512                 if (gclass == klass->generic_container->context.gclass)
513                         return NULL;
514                 nt = dup_type (type, type);
515                 nt->type = MONO_TYPE_GENERICINST;
516                 nt->data.generic_class = gclass;
517                 return nt;
518         }
519         default:
520                 return NULL;
521         }
522         return NULL;
523 }
524
525 MonoInflatedGenericClass*
526 mono_get_inflated_generic_class (MonoGenericClass *gclass)
527 {
528         g_assert (gclass->is_inflated);
529         mono_class_create_generic ((MonoInflatedGenericClass *) gclass);
530         return (MonoInflatedGenericClass *) gclass;
531 }
532
533 MonoType*
534 mono_class_inflate_generic_type (MonoType *type, MonoGenericContext *context)
535 {
536         MonoType *inflated = inflate_generic_type (type, context);
537
538         if (!inflated)
539                 return dup_type (type, type);
540
541         mono_stats.inflated_type_count++;
542         return inflated;
543 }
544
545 static MonoGenericContext *
546 inflate_generic_context (MonoGenericContext *context, MonoGenericContext *inflate_with)
547 {
548         MonoGenericClass *gclass = NULL;
549         MonoGenericMethod *gmethod = NULL;
550         MonoGenericContext *res;
551
552         if (context->gclass)
553                 gclass = inflate_generic_class (context->gclass, inflate_with);
554
555         if (context->gmethod) {
556                 MonoGenericInst *ninst = mono_metadata_inflate_generic_inst (context->gmethod->inst, inflate_with);
557                 if (gclass == context->gclass && ninst == context->gmethod->inst) {
558                         gmethod = context->gmethod;
559                 } else {
560                         gmethod = g_new0 (MonoGenericMethod, 1);
561                         gmethod->generic_class = gclass;
562                         gmethod->container = context->container;
563                         gmethod->inst = ninst;
564                 }
565         }
566
567         if (gclass == context->gclass && gmethod == context->gmethod)
568                 return context;
569
570         res = g_new0 (MonoGenericContext, 1);
571
572         res->container = gmethod ? gmethod->container : context->container;
573         res->gclass = gclass;
574         res->gmethod = gmethod;
575
576         return res;
577 }
578
579 MonoMethod *
580 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericContext *context)
581 {
582         return mono_class_inflate_generic_method_full (method, NULL, context);
583 }
584
585 /**
586  * mono_class_inflate_generic_method:
587  *
588  * Instantiate method @method with the generic context @context.
589  * BEWARE: All non-trivial fields are invalid, including klass, signature, and header.
590  *         Use mono_get_inflated_method (), mono_method_signature () and mono_method_get_header () to get the correct values.
591  */
592 MonoMethod*
593 mono_class_inflate_generic_method_full (MonoMethod *method, MonoClass *klass_hint, MonoGenericContext *context)
594 {
595         MonoMethod *result;
596         MonoMethodInflated *iresult;
597         MonoMethodSignature *sig;
598
599         /* The `method' has already been instantiated before -> we need to create a new context. */
600         while (method->is_inflated) {
601                 MonoMethodInflated *imethod = (MonoMethodInflated *) method;
602                 context = inflate_generic_context (imethod->context, context);
603                 if (context == imethod->context)
604                         return method;
605                 method = imethod->declaring;
606         }
607
608         if (!method->generic_container && !method->klass->generic_container)
609                 return method;
610
611         mono_stats.inflated_method_count++;
612         iresult = g_new0 (MonoMethodInflated, 1);
613
614         sig = mono_method_signature (method);
615         if (sig->pinvoke) {
616                 iresult->method.pinvoke = *(MonoMethodPInvoke*)method;
617         } else {
618                 iresult->method.normal = *(MonoMethodNormal*)method;
619                 iresult->method.normal.header = NULL;
620         }
621
622         result = (MonoMethod *) iresult;
623         result->is_inflated = 1;
624         result->signature = NULL;
625         iresult->context = context;
626         iresult->declaring = method;
627
628         if (!klass_hint || !klass_hint->generic_class ||
629             klass_hint->generic_class->container_class != method->klass ||
630             klass_hint->generic_class->inst != context->gclass->inst)
631                 klass_hint = NULL;
632
633         if (method->klass->generic_container)
634                 result->klass = klass_hint;
635
636         if (!result->klass) {
637                 MonoType *inflated = inflate_generic_type (&method->klass->byval_arg, context);
638                 result->klass = inflated ? mono_class_from_mono_type (inflated) : method->klass;
639         }
640
641         if (method->generic_container && !context->gmethod) {
642                 MonoGenericMethod *gmethod = g_memdup (method->generic_container->context.gmethod, sizeof (*gmethod));
643                 gmethod->generic_class = result->klass->generic_class;
644
645                 context = g_new0 (MonoGenericContext, 1);
646                 context->container = method->generic_container;
647                 context->gclass = result->klass->generic_class;
648                 context->gmethod = gmethod;
649
650                 iresult->context = context;
651         }
652
653         return result;
654 }
655
656 /**
657  * mono_get_inflated_method:
658  *
659  * For performance reasons, mono_class_inflate_generic_method() does not actually instantiate the
660  * method, it just "prepares" it for that.  If you really need to fully instantiate the method
661  * (including its signature and header), call this method.
662  */
663 MonoMethod *
664 mono_get_inflated_method (MonoMethod *method)
665 {
666         return method;
667 }
668
669 /** 
670  * mono_class_find_enum_basetype:
671  * @class: The enum class
672  *
673  *   Determine the basetype of an enum by iterating through its fields. We do this
674  * in a separate function since it is cheaper than calling mono_class_setup_fields.
675  */
676 static MonoType*
677 mono_class_find_enum_basetype (MonoClass *class)
678 {
679         MonoImage *m = class->image; 
680         const int top = class->field.count;
681         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
682         int i;
683
684         g_assert (class->enumtype);
685
686         /*
687          * Fetch all the field information.
688          */
689         for (i = 0; i < top; i++){
690                 const char *sig;
691                 guint32 cols [MONO_FIELD_SIZE];
692                 int idx = class->field.first + i;
693                 MonoGenericContainer *container = NULL;
694                 MonoType *ftype;
695
696                 mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
697                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
698                 mono_metadata_decode_value (sig, &sig);
699                 /* FIELD signature == 0x06 */
700                 g_assert (*sig == 0x06);
701                 if (class->generic_container)
702                         container = class->generic_container;
703                 else if (class->generic_class) {
704                         MonoClass *gklass = class->generic_class->container_class;
705
706                         container = gklass->generic_container;
707                         g_assert (container);
708                 }
709                 ftype = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
710                 if (!ftype)
711                         return NULL;
712                 if (class->generic_class) {
713                         ftype = mono_class_inflate_generic_type (ftype, class->generic_class->context);
714                         ftype->attrs = cols [MONO_FIELD_FLAGS];
715                 }
716
717                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC))
718                         return ftype;
719         }
720
721         return NULL;
722 }
723
724 /** 
725  * mono_class_setup_fields:
726  * @class: The class to initialize
727  *
728  * Initializes the class->fields.
729  * Assumes the loader lock is held.
730  */
731 static void
732 mono_class_setup_fields (MonoClass *class)
733 {
734         MonoImage *m = class->image; 
735         const int top = class->field.count;
736         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
737         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
738         int i, blittable = TRUE, real_size = 0;
739         guint32 packing_size = 0;
740         gboolean explicit_size;
741         MonoClassField *field;
742         MonoGenericContainer *container = NULL;
743         MonoClass *gklass = NULL;
744
745         if (class->size_inited)
746                 return;
747
748         if (class->inited)
749                 mono_class_init (class);
750
751         class->instance_size = 0;
752         class->class_size = 0;
753
754         if (class->parent) {
755                 if (!class->parent->size_inited)
756                         mono_class_setup_fields (class->parent);
757                 class->instance_size += class->parent->instance_size;
758                 class->min_align = class->parent->min_align;
759                 /* we use |= since it may have been set already */
760                 class->has_references |= class->parent->has_references;
761                 blittable = class->parent->blittable;
762         } else {
763                 class->instance_size = sizeof (MonoObject);
764                 class->min_align = 1;
765         }
766
767         /* Get the real size */
768         explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
769
770         if (explicit_size) {
771                 g_assert ((packing_size & 0xfffffff0) == 0);
772                 class->packing_size = packing_size;
773                 real_size += class->instance_size;
774         }
775
776         if (!top) {
777                 if (explicit_size && real_size) {
778                         class->instance_size = MAX (real_size, class->instance_size);
779                 }
780                 class->size_inited = 1;
781                 class->blittable = blittable;
782                 return;
783         }
784
785         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT)
786                 blittable = FALSE;
787
788         /* Prevent infinite loops if the class references itself */
789         class->size_inited = 1;
790
791         class->fields = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoClassField) * top);
792
793         if (class->generic_container) {
794                 container = class->generic_container;
795         } else if (class->generic_class) {
796                 gklass = class->generic_class->container_class;
797                 container = gklass->generic_container;
798                 g_assert (container);
799
800                 mono_class_setup_fields (gklass);
801         }
802
803         /*
804          * Fetch all the field information.
805          */
806         for (i = 0; i < top; i++){
807                 int idx = class->field.first + i;
808                 field = &class->fields [i];
809
810                 field->parent = class;
811
812                 if (class->generic_class) {
813                         MonoClassField *gfield = &gklass->fields [i];
814                         MonoInflatedField *ifield = g_new0 (MonoInflatedField, 1);
815
816                         ifield->generic_type = gfield->type;
817                         field->name = gfield->name;
818                         field->generic_info = ifield;
819                         field->type = mono_class_inflate_generic_type (gfield->type, class->generic_class->context);
820                         field->type->attrs = gfield->type->attrs;
821                         if (mono_field_is_deleted (field))
822                                 continue;
823                         field->offset = gfield->offset;
824                         field->data = gfield->data;
825                 } else {
826                         guint32 rva;
827                         const char *sig;
828                         guint32 cols [MONO_FIELD_SIZE];
829
830                         mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
831                         /* The name is needed for fieldrefs */
832                         field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
833                         sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
834                         mono_metadata_decode_value (sig, &sig);
835                         /* FIELD signature == 0x06 */
836                         g_assert (*sig == 0x06);
837                         field->type = mono_metadata_parse_type_full (m, container, MONO_PARSE_FIELD, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
838                         if (!field->type) {
839                                 mono_class_set_failure (class, MONO_EXCEPTION_TYPE_LOAD, NULL);
840                                 continue;
841                         }
842                         if (mono_field_is_deleted (field))
843                                 continue;
844                         if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
845                                 mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
846                                 if (field->offset == (guint32)-1 && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
847                                         g_warning ("%s not initialized correctly (missing field layout info for %s)",
848                                                    class->name, field->name);
849                         }
850
851                         if (field->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
852                                 mono_metadata_field_info (m, idx, NULL, &rva, NULL);
853                                 if (!rva)
854                                         g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
855                                 field->data = mono_image_rva_map (class->image, rva);
856                         }
857                 }
858
859                 /* Only do these checks if we still think this type is blittable */
860                 if (blittable && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
861                         if (field->type->byref || MONO_TYPE_IS_REFERENCE (field->type)) {
862                                 blittable = FALSE;
863                         } else {
864                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
865                                 if (!field_class || !field_class->blittable)
866                                         blittable = FALSE;
867                         }
868                 }
869
870                 if (class->enumtype && !(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
871                         class->enum_basetype = field->type;
872                         class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
873                         blittable = class->element_class->blittable;
874                 }
875
876                 /* The def_value of fields is compute lazily during vtable creation */
877         }
878
879         if (class == mono_defaults.string_class)
880                 blittable = FALSE;
881
882         class->blittable = blittable;
883
884         if (class->enumtype && !class->enum_basetype) {
885                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
886                         G_BREAKPOINT ();
887         }
888         if (explicit_size && real_size) {
889                 class->instance_size = MAX (real_size, class->instance_size);
890         }
891
892         mono_class_layout_fields (class);
893 }
894
895 /** 
896  * mono_class_setup_fields_locking:
897  * @class: The class to initialize
898  *
899  * Initializes the class->fields.
900  * Aquires the loader lock.
901  */
902 static void
903 mono_class_setup_fields_locking (MonoClass *class)
904 {
905         mono_loader_lock ();
906         mono_class_setup_fields (class);
907         mono_loader_unlock ();
908 }
909
910 /*
911  * mono_class_has_references:
912  *
913  *   Returns whenever @klass->has_references is set, initializing it if needed.
914  * Aquires the loader lock.
915  */
916 static gboolean
917 mono_class_has_references (MonoClass *klass)
918 {
919         if (klass->init_pending) {
920                 /* Be conservative */
921                 return TRUE;
922         } else {
923                 mono_class_init (klass);
924
925                 return klass->has_references;
926         }
927 }
928
929 /* useful until we keep track of gc-references in corlib etc. */
930 #define IS_GC_REFERENCE(t) ((t)->type == MONO_TYPE_U || (t)->type == MONO_TYPE_I || (t)->type == MONO_TYPE_PTR)
931
932 /*
933  * LOCKING: this is supposed to be called with the loader lock held.
934  */
935 void
936 mono_class_layout_fields (MonoClass *class)
937 {
938         int i;
939         const int top = class->field.count;
940         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
941         guint32 pass, passes, real_size;
942         gboolean gc_aware_layout = FALSE;
943         MonoClassField *field;
944
945         if (class->generic_container ||
946             (class->generic_class && class->generic_class->inst->is_open))
947                 return;
948
949         /*
950          * Enable GC aware auto layout: in this mode, reference
951          * fields are grouped together inside objects, increasing collector 
952          * performance.
953          * Requires that all classes whose layout is known to native code be annotated
954          * with [StructLayout (LayoutKind.Sequential)]
955          * Value types have gc_aware_layout disabled by default, as per
956          * what the default is for other runtimes.
957          */
958          /* corlib is missing [StructLayout] directives in many places */
959         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
960                 if (class->image != mono_defaults.corlib &&
961                         class->byval_arg.type != MONO_TYPE_VALUETYPE)
962                         gc_aware_layout = TRUE;
963         }
964
965         /* Compute klass->has_references */
966         /* 
967          * Process non-static fields first, since static fields might recursively
968          * refer to the class itself.
969          */
970         for (i = 0; i < top; i++) {
971                 MonoType *ftype;
972
973                 field = &class->fields [i];
974
975                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
976                         ftype = mono_type_get_underlying_type (field->type);
977                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
978                                 class->has_references = TRUE;
979                 }
980         }
981
982         for (i = 0; i < top; i++) {
983                 MonoType *ftype;
984
985                 field = &class->fields [i];
986
987                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
988                         ftype = mono_type_get_underlying_type (field->type);
989                         if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype)))))
990                                 class->has_static_refs = TRUE;
991                 }
992         }
993
994         for (i = 0; i < top; i++) {
995                 MonoType *ftype;
996
997                 field = &class->fields [i];
998
999                 ftype = mono_type_get_underlying_type (field->type);
1000                 if (MONO_TYPE_IS_REFERENCE (ftype) || IS_GC_REFERENCE (ftype) || ((MONO_TYPE_ISSTRUCT (ftype) && mono_class_has_references (mono_class_from_mono_type (ftype))))) {
1001                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1002                                 class->has_static_refs = TRUE;
1003                         else
1004                                 class->has_references = TRUE;
1005                 }
1006         }
1007
1008         /*
1009          * Compute field layout and total size (not considering static fields)
1010          */
1011
1012         switch (layout) {
1013         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
1014         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
1015
1016                 if (gc_aware_layout)
1017                         passes = 2;
1018                 else
1019                         passes = 1;
1020
1021                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
1022                         passes = 1;
1023
1024                 if (class->parent)
1025                         real_size = class->parent->instance_size;
1026                 else
1027                         real_size = sizeof (MonoObject);
1028
1029                 for (pass = 0; pass < passes; ++pass) {
1030                         for (i = 0; i < top; i++){
1031                                 int size, align;
1032
1033                                 field = &class->fields [i];
1034
1035                                 if (mono_field_is_deleted (field))
1036                                         continue;
1037                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1038                                         continue;
1039
1040                                 if (gc_aware_layout) {
1041                                         /* 
1042                                          * We process fields with reference type in the first pass,
1043                                          * and fields with non-reference type in the second pass.
1044                                          * We use IS_POINTER instead of IS_REFERENCE because in
1045                                          * some internal structures, we store GC_MALLOCed memory
1046                                          * in IntPtr fields...
1047                                          */
1048                                         if (MONO_TYPE_IS_POINTER (field->type)) {
1049                                                 if (pass == 1)
1050                                                         continue;
1051                                         } else {
1052                                                 if (pass == 0)
1053                                                         continue;
1054                                         }
1055                                 }
1056
1057                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
1058                                         (strcmp (field->name, "$PRIVATE$") == 0)) {
1059                                         /* This field is a hack inserted by MCS to empty structures */
1060                                         continue;
1061                                 }
1062
1063                                 size = mono_type_size (field->type, &align);
1064                         
1065                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
1066                                 align = class->packing_size ? MIN (class->packing_size, align): align;
1067                                 class->min_align = MAX (align, class->min_align);
1068                                 field->offset = real_size;
1069                                 field->offset += align - 1;
1070                                 field->offset &= ~(align - 1);
1071                                 real_size = field->offset + size;
1072                         }
1073
1074                         class->instance_size = MAX (real_size, class->instance_size);
1075        
1076                         if (class->instance_size & (class->min_align - 1)) {
1077                                 class->instance_size += class->min_align - 1;
1078                                 class->instance_size &= ~(class->min_align - 1);
1079                         }
1080                 }
1081                 break;
1082         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
1083                 real_size = 0;
1084                 for (i = 0; i < top; i++) {
1085                         int size, align;
1086
1087                         field = &class->fields [i];
1088
1089                         /*
1090                          * There must be info about all the fields in a type if it
1091                          * uses explicit layout.
1092                          */
1093
1094                         if (mono_field_is_deleted (field))
1095                                 continue;
1096                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1097                                 continue;
1098
1099                         size = mono_type_size (field->type, &align);
1100                         
1101                         /*
1102                          * When we get here, field->offset is already set by the
1103                          * loader (for either runtime fields or fields loaded from metadata).
1104                          * The offset is from the start of the object: this works for both
1105                          * classes and valuetypes.
1106                          */
1107                         field->offset += sizeof (MonoObject);
1108
1109                         /*
1110                          * Calc max size.
1111                          */
1112                         real_size = MAX (real_size, size + field->offset);
1113                 }
1114                 class->instance_size = MAX (real_size, class->instance_size);
1115                 break;
1116         }
1117
1118         class->size_inited = 1;
1119
1120         /*
1121          * Compute static field layout and size
1122          */
1123         for (i = 0; i < top; i++){
1124                 int size, align;
1125
1126                 field = &class->fields [i];
1127                         
1128                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC) || field->type->attrs & FIELD_ATTRIBUTE_LITERAL)
1129                         continue;
1130                 if (mono_field_is_deleted (field))
1131                         continue;
1132
1133                 size = mono_type_size (field->type, &align);
1134                 field->offset = class->class_size;
1135                 field->offset += align - 1;
1136                 field->offset &= ~(align - 1);
1137                 class->class_size = field->offset + size;
1138         }
1139 }
1140
1141 /*
1142  * mono_class_setup_methods:
1143  *
1144  *   Initializes the 'methods' array in the klass.
1145  * Calling this method should be avoided if possible since it allocates a lot 
1146  * of long-living MonoMethod structures.
1147  */
1148 void
1149 mono_class_setup_methods (MonoClass *class)
1150 {
1151         int i;
1152         MonoMethod **methods;
1153
1154         if (class->methods)
1155                 return;
1156
1157         mono_loader_lock ();
1158
1159         if (class->methods) {
1160                 mono_loader_unlock ();
1161                 return;
1162         }
1163
1164         //printf ("INIT: %s.%s\n", class->name_space, class->name);
1165
1166         if (!class->methods) {
1167                 methods = mono_mempool_alloc (class->image->mempool, sizeof (MonoMethod*) * class->method.count);
1168                 for (i = 0; i < class->method.count; ++i) {
1169                         methods [i] = mono_get_method (class->image, MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
1170                 }
1171         }
1172
1173         if (MONO_CLASS_IS_INTERFACE (class))
1174                 for (i = 0; i < class->method.count; ++i)
1175                         methods [i]->slot = i;
1176
1177         /* Leave this assignment as the last op in this function */
1178         class->methods = methods;
1179
1180         mono_loader_unlock ();
1181 }
1182
1183
1184 static void
1185 mono_class_setup_properties (MonoClass *class)
1186 {
1187         guint startm, endm, i, j;
1188         guint32 cols [MONO_PROPERTY_SIZE];
1189         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
1190         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1191         MonoProperty *properties;
1192         guint32 last;
1193
1194         if (class->properties)
1195                 return;
1196
1197         mono_loader_lock ();
1198
1199         if (class->properties) {
1200                 mono_loader_unlock ();
1201                 return;
1202         }
1203
1204         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1205         class->property.count = last - class->property.first;
1206
1207         if (class->property.count)
1208                 mono_class_setup_methods (class);
1209
1210         properties = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoProperty) * class->property.count);
1211         for (i = class->property.first; i < last; ++i) {
1212                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
1213                 properties [i - class->property.first].parent = class;
1214                 properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
1215                 properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
1216
1217                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
1218                 for (j = startm; j < endm; ++j) {
1219                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1220                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1221                         case METHOD_SEMANTIC_SETTER:
1222                                 properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1223                                 break;
1224                         case METHOD_SEMANTIC_GETTER:
1225                                 properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1226                                 break;
1227                         default:
1228                                 break;
1229                         }
1230                 }
1231         }
1232
1233         /* Leave this assignment as the last op in the function */
1234         class->properties = properties;
1235
1236         mono_loader_unlock ();
1237 }
1238
1239 static void
1240 inflate_event (MonoClass *class, MonoEvent *event, MonoInflatedGenericClass *gclass)
1241 {
1242         event->parent = class;
1243
1244         if (event->add) {
1245                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1246                         event->add, class, gclass->generic_class.context);
1247
1248                 event->add = mono_get_inflated_method (inflated);
1249         }
1250
1251         if (event->remove) {
1252                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1253                         event->remove, class, gclass->generic_class.context);
1254
1255                 event->remove = mono_get_inflated_method (inflated);
1256         }
1257
1258         if (event->raise) {
1259                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1260                         event->raise, class, gclass->generic_class.context);
1261
1262                 event->raise = mono_get_inflated_method (inflated);
1263         }
1264
1265         if (event->other) {
1266                 MonoMethod *inflated = mono_class_inflate_generic_method_full (
1267                         event->other, class, gclass->generic_class.context);
1268
1269                 event->other = mono_get_inflated_method (inflated);
1270         }
1271 }
1272
1273 static void
1274 mono_class_setup_events (MonoClass *class)
1275 {
1276         guint startm, endm, i, j;
1277         guint32 cols [MONO_EVENT_SIZE];
1278         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
1279         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
1280         guint32 last;
1281         MonoEvent *events;
1282
1283         if (class->events)
1284                 return;
1285
1286         mono_loader_lock ();
1287
1288         if (class->events) {
1289                 mono_loader_unlock ();
1290                 return;
1291         }
1292
1293         if (class->generic_class) {
1294                 MonoInflatedGenericClass *gclass;
1295                 MonoClass *gklass;
1296
1297                 gclass = mono_get_inflated_generic_class (class->generic_class);
1298                 gklass = gclass->generic_class.container_class;
1299
1300                 mono_class_setup_events (gklass);
1301                 class->event = gklass->event;
1302
1303                 class->events = g_new0 (MonoEvent, class->event.count);
1304
1305                 for (i = 0; i < class->event.count; i++) {
1306                         class->events [i] = gklass->events [i];
1307                         inflate_event (class, &class->events [i], gclass);
1308                 }
1309
1310                 mono_loader_unlock ();
1311                 return;
1312         }
1313
1314         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &last);
1315         class->event.count = last - class->event.first;
1316
1317         if (class->event.count)
1318                 mono_class_setup_methods (class);
1319
1320         events = mono_mempool_alloc0 (class->image->mempool, sizeof (MonoEvent) * class->event.count);
1321         for (i = class->event.first; i < last; ++i) {
1322                 MonoEvent *event = &events [i - class->event.first];
1323                         
1324                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
1325                 event->parent = class;
1326                 event->attrs = cols [MONO_EVENT_FLAGS];
1327                 event->name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
1328
1329                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
1330                 for (j = startm; j < endm; ++j) {
1331                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
1332                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
1333                         case METHOD_SEMANTIC_ADD_ON:
1334                                 event->add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1335                                 break;
1336                         case METHOD_SEMANTIC_REMOVE_ON:
1337                                 event->remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1338                                 break;
1339                         case METHOD_SEMANTIC_FIRE:
1340                                 event->raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1341                                 break;
1342                         case METHOD_SEMANTIC_OTHER: {
1343                                 int n = 0;
1344
1345                                 if (event->other == NULL) {
1346                                         event->other = g_new0 (MonoMethod*, 1);
1347                                 } else {
1348                                         while (event->other [n])
1349                                                 n++;
1350                                         event->other = g_realloc (event->other, (n + 1) * sizeof (MonoMethod*));
1351                                 }
1352                                 event->other [n] = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
1353                                 break;
1354                         }
1355                         default:
1356                                 break;
1357                         }
1358                 }
1359         }
1360         /* Leave this assignment as the last op in the function */
1361         class->events = events;
1362
1363         mono_loader_unlock ();
1364 }
1365
1366 static guint
1367 mono_get_unique_iid (MonoClass *class)
1368 {
1369         static GHashTable *iid_hash = NULL;
1370         static guint iid = 0;
1371         char *str, *type_name;
1372         gpointer value;
1373         int generic_id;
1374         
1375         g_assert (MONO_CLASS_IS_INTERFACE (class));
1376
1377         mono_loader_lock ();
1378
1379         if (!iid_hash)
1380                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
1381
1382         if (class->generic_class && !class->generic_class->inst->is_open) {
1383                 generic_id = class->generic_class->inst->id;
1384                 g_assert (generic_id != 0);
1385         } else
1386                 generic_id = 0;
1387
1388         type_name = mono_type_full_name (&class->byval_arg);
1389         str = g_strdup_printf ("%s|%s|%d", class->image->name, type_name, generic_id);
1390         g_free (type_name);
1391
1392         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
1393                 mono_loader_unlock ();
1394                 if (mono_print_vtable)
1395                         printf ("Interface: reusing id %d for %s\n", iid, str);
1396                 g_free (str);
1397                 return GPOINTER_TO_INT (value);
1398         } else {
1399                 if (mono_print_vtable)
1400                         printf ("Interface: assigned id %d to %s\n", iid, str);
1401                 g_hash_table_insert (iid_hash, str, GINT_TO_POINTER (iid));
1402                 ++iid;
1403         }
1404
1405         mono_loader_unlock ();
1406
1407         g_assert (iid <= 65535);
1408         return iid - 1;
1409 }
1410
1411 static void
1412 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
1413 {
1414         int i;
1415         MonoClass *ic;
1416         
1417         for (i = 0; i < klass->interface_count; i++) {
1418                 ic = klass->interfaces [i];
1419
1420                 if (*res == NULL)
1421                         *res = g_ptr_array_new ();
1422                 g_ptr_array_add (*res, ic);
1423                 mono_class_init (ic);
1424
1425                 collect_implemented_interfaces_aux (ic, res);
1426         }
1427 }
1428
1429 GPtrArray*
1430 mono_class_get_implemented_interfaces (MonoClass *klass)
1431 {
1432         GPtrArray *res = NULL;
1433
1434         collect_implemented_interfaces_aux (klass, &res);
1435         return res;
1436 }
1437
1438 typedef struct _IOffsetInfo IOffsetInfo;
1439 struct _IOffsetInfo {
1440         IOffsetInfo *next;
1441         int size;
1442         int next_free;
1443         int data [MONO_ZERO_LEN_ARRAY];
1444 };
1445
1446 static IOffsetInfo *cached_offset_info = NULL;
1447 static int next_offset_info_size = 128;
1448
1449 static int*
1450 cache_interface_offsets (int max_iid, int *data)
1451 {
1452         IOffsetInfo *cached_info;
1453         int *cached;
1454         int new_size;
1455         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1456                 cached = cached_info->data;
1457                 while (cached < cached_info->data + cached_info->size && *cached) {
1458                         if (*cached == max_iid) {
1459                                 int i, matched = TRUE;
1460                                 cached++;
1461                                 for (i = 0; i < max_iid; ++i) {
1462                                         if (cached [i] != data [i]) {
1463                                                 matched = FALSE;
1464                                                 break;
1465                                         }
1466                                 }
1467                                 if (matched)
1468                                         return cached;
1469                                 cached += max_iid;
1470                         } else {
1471                                 cached += *cached + 1;
1472                         }
1473                 }
1474         }
1475         /* find a free slot */
1476         for (cached_info = cached_offset_info; cached_info; cached_info = cached_info->next) {
1477                 if (cached_info->size - cached_info->next_free >= max_iid + 1) {
1478                         cached = &cached_info->data [cached_info->next_free];
1479                         *cached++ = max_iid;
1480                         memcpy (cached, data, max_iid * sizeof (int));
1481                         cached_info->next_free += max_iid + 1;
1482                         return cached;
1483                 }
1484         }
1485         /* allocate a new chunk */
1486         if (max_iid + 1 < next_offset_info_size) {
1487                 new_size = next_offset_info_size;
1488                 if (next_offset_info_size < 4096)
1489                         next_offset_info_size += next_offset_info_size >> 2;
1490         } else {
1491                 new_size = max_iid + 1;
1492         }
1493         cached_info = g_malloc0 (sizeof (IOffsetInfo) + sizeof (int) * new_size);
1494         cached_info->size = new_size;
1495         /*g_print ("allocated %d offset entries at %p (total: %d)\n", new_size, cached_info->data, offset_info_total_size);*/
1496         cached = &cached_info->data [0];
1497         *cached++ = max_iid;
1498         memcpy (cached, data, max_iid * sizeof (int));
1499         cached_info->next_free += max_iid + 1;
1500         cached_info->next = cached_offset_info;
1501         cached_offset_info = cached_info;
1502         return cached;
1503 }
1504
1505 static int
1506 setup_interface_offsets (MonoClass *class, int cur_slot)
1507 {
1508         MonoClass *k, *ic;
1509         int i, max_iid;
1510         int *cached_data;
1511         GPtrArray *ifaces;
1512
1513         /* compute maximum number of slots and maximum interface id */
1514         max_iid = 0;
1515         for (k = class; k ; k = k->parent) {
1516                 for (i = 0; i < k->interface_count; i++) {
1517                         ic = k->interfaces [i];
1518
1519                         if (!ic->inited)
1520                                 mono_class_init (ic);
1521
1522                         if (max_iid < ic->interface_id)
1523                                 max_iid = ic->interface_id;
1524                 }
1525                 ifaces = mono_class_get_implemented_interfaces (k);
1526                 if (ifaces) {
1527                         for (i = 0; i < ifaces->len; ++i) {
1528                                 ic = g_ptr_array_index (ifaces, i);
1529                                 if (max_iid < ic->interface_id)
1530                                         max_iid = ic->interface_id;
1531                         }
1532                         g_ptr_array_free (ifaces, TRUE);
1533                 }
1534         }
1535
1536         if (MONO_CLASS_IS_INTERFACE (class)) {
1537                 if (max_iid < class->interface_id)
1538                         max_iid = class->interface_id;
1539         }
1540         class->max_interface_id = max_iid;
1541         /* compute vtable offset for interfaces */
1542         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
1543
1544         for (i = 0; i <= max_iid; i++)
1545                 class->interface_offsets [i] = -1;
1546
1547         ifaces = mono_class_get_implemented_interfaces (class);
1548         if (ifaces) {
1549                 for (i = 0; i < ifaces->len; ++i) {
1550                         ic = g_ptr_array_index (ifaces, i);
1551                         class->interface_offsets [ic->interface_id] = cur_slot;
1552                         cur_slot += ic->method.count;
1553                 }
1554                 g_ptr_array_free (ifaces, TRUE);
1555         }
1556
1557         for (k = class->parent; k ; k = k->parent) {
1558                 ifaces = mono_class_get_implemented_interfaces (k);
1559                 if (ifaces) {
1560                         for (i = 0; i < ifaces->len; ++i) {
1561                                 ic = g_ptr_array_index (ifaces, i);
1562
1563                                 if (class->interface_offsets [ic->interface_id] == -1) {
1564                                         int io = k->interface_offsets [ic->interface_id];
1565
1566                                         g_assert (io >= 0);
1567
1568                                         class->interface_offsets [ic->interface_id] = io;
1569                                 }
1570                         }
1571                         g_ptr_array_free (ifaces, TRUE);
1572                 }
1573         }
1574
1575         if (MONO_CLASS_IS_INTERFACE (class))
1576                 class->interface_offsets [class->interface_id] = cur_slot;
1577
1578         cached_data = cache_interface_offsets (max_iid + 1, class->interface_offsets);
1579         g_free (class->interface_offsets);
1580         class->interface_offsets = cached_data;
1581
1582         return cur_slot;
1583 }
1584
1585 static void
1586 setup_generic_vtable (MonoClass *class)
1587 {
1588         MonoClass *gklass;
1589         int i;
1590
1591         gklass = class->generic_class->container_class;
1592
1593         mono_class_init (gklass);
1594         class->vtable_size = gklass->vtable_size;
1595
1596         class->vtable = g_new0 (MonoMethod*, class->vtable_size);
1597         memcpy (class->vtable, gklass->vtable,  sizeof (MonoMethod*) * class->vtable_size);
1598
1599         for (i = 0; i < class->vtable_size; i++) {
1600                 MonoMethod *m = class->vtable [i];
1601
1602                 if (!m)
1603                         continue;
1604
1605                 m = mono_class_inflate_generic_method_full (m, class, class->generic_class->context);
1606                 class->vtable [i] = m;
1607         }
1608
1609         class->max_interface_id = gklass->max_interface_id;
1610         class->interface_offsets = g_new0 (gint, gklass->max_interface_id + 1);
1611         memcpy (class->interface_offsets, gklass->interface_offsets,
1612                 sizeof (gint) * (gklass->max_interface_id + 1));
1613 }
1614
1615 void
1616 mono_class_setup_vtable (MonoClass *class)
1617 {
1618         MonoMethod **overrides;
1619         MonoGenericContext *context;
1620         guint32 type_token;
1621         int onum = 0;
1622
1623         if (class->vtable)
1624                 return;
1625
1626         mono_class_setup_methods (class);
1627
1628         if (MONO_CLASS_IS_INTERFACE (class))
1629                 return;
1630
1631         mono_loader_lock ();
1632
1633         if (class->vtable) {
1634                 mono_loader_unlock ();
1635                 return;
1636         }
1637
1638         if (class->generic_class) {
1639                 if (class->generic_class->inst->is_open) {
1640                         setup_generic_vtable (class);
1641                         mono_loader_unlock ();
1642                         return;
1643                 }
1644
1645                 context = class->generic_class->context;
1646                 type_token = class->generic_class->container_class->type_token;
1647         } else {
1648                 context = (MonoGenericContext *) class->generic_container;              
1649                 type_token = class->type_token;
1650         }
1651
1652         if (class->image->dynamic)
1653                 mono_reflection_get_dynamic_overrides (class, &overrides, &onum);
1654         else
1655                 mono_class_get_overrides_full (class->image, type_token, &overrides, &onum, context);
1656
1657         mono_class_setup_vtable_general (class, overrides, onum);
1658         g_free (overrides);
1659
1660         mono_loader_unlock ();
1661 }
1662
1663 /*
1664  * LOCKING: this is supposed to be called with the loader lock held.
1665  */
1666 void
1667 mono_class_setup_vtable_general (MonoClass *class, MonoMethod **overrides, int onum)
1668 {
1669         MonoClass *k, *ic;
1670         MonoMethod **vtable;
1671         int i, max_vtsize = 0, max_iid, cur_slot = 0;
1672         GPtrArray *ifaces, *pifaces = NULL;
1673         GHashTable *override_map = NULL;
1674         gboolean security_enabled = mono_is_security_manager_active ();
1675
1676         if (class->vtable)
1677                 return;
1678
1679         if (class->generic_class && class->generic_class->inst->is_open) {
1680                 setup_generic_vtable (class);
1681                 return;
1682         }
1683
1684         ifaces = mono_class_get_implemented_interfaces (class);
1685         if (ifaces) {
1686                 for (i = 0; i < ifaces->len; i++) {
1687                         MonoClass *ic = g_ptr_array_index (ifaces, i);
1688                         max_vtsize += ic->method.count;
1689                 }
1690                 g_ptr_array_free (ifaces, TRUE);
1691         }
1692         
1693         if (class->parent) {
1694                 mono_class_init (class->parent);
1695                 mono_class_setup_vtable (class->parent);
1696                 max_vtsize += class->parent->vtable_size;
1697                 cur_slot = class->parent->vtable_size;
1698         }
1699
1700         max_vtsize += class->method.count;
1701
1702         vtable = alloca (sizeof (gpointer) * max_vtsize);
1703         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
1704
1705         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
1706
1707         cur_slot = setup_interface_offsets (class, cur_slot);
1708         max_iid = class->max_interface_id;
1709
1710         if (class->parent && class->parent->vtable_size)
1711                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
1712
1713         /* override interface methods */
1714         for (i = 0; i < onum; i++) {
1715                 MonoMethod *decl = overrides [i*2];
1716                 if (MONO_CLASS_IS_INTERFACE (decl->klass)) {
1717                         int dslot;
1718                         mono_class_setup_methods (decl->klass);
1719                         g_assert (decl->slot != -1);
1720                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
1721                         vtable [dslot] = overrides [i*2 + 1];
1722                         vtable [dslot]->slot = dslot;
1723                         if (!override_map)
1724                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1725
1726                         g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
1727                 }
1728         }
1729
1730         for (k = class; k ; k = k->parent) {
1731                 int nifaces = 0;
1732
1733                 ifaces = mono_class_get_implemented_interfaces (k);
1734                 if (ifaces) {
1735                         nifaces = ifaces->len;
1736                         if (k->generic_class) {
1737                                 pifaces = mono_class_get_implemented_interfaces (
1738                                         k->generic_class->container_class);
1739                                 g_assert (pifaces && (pifaces->len == nifaces));
1740                         }
1741                 }
1742                 for (i = 0; i < nifaces; i++) {
1743                         MonoClass *pic = NULL;
1744                         int j, l, io;
1745
1746                         ic = g_ptr_array_index (ifaces, i);
1747                         if (pifaces)
1748                                 pic = g_ptr_array_index (pifaces, i);
1749                         g_assert (ic->interface_id <= k->max_interface_id);
1750                         io = k->interface_offsets [ic->interface_id];
1751
1752                         g_assert (io >= 0);
1753                         g_assert (io <= max_vtsize);
1754
1755                         if (k == class) {
1756                                 mono_class_setup_methods (ic);
1757                                 for (l = 0; l < ic->method.count; l++) {
1758                                         MonoMethod *im = ic->methods [l];                                               
1759
1760                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1761                                                 continue;
1762
1763                                         for (j = 0; j < class->method.count; ++j) {
1764                                                 MonoMethod *cm = class->methods [j];
1765                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1766                                                     !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
1767                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
1768                                                         continue;
1769                                                 if (!strcmp(cm->name, im->name) && 
1770                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1771
1772                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1773                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1774                                                                 mono_secman_inheritancedemand_method (cm, im);
1775                                                         }
1776
1777                                                         g_assert (io + l <= max_vtsize);
1778                                                         vtable [io + l] = cm;
1779                                                 }
1780                                         }
1781                                 }
1782                         } else {
1783                                 /* already implemented */
1784                                 if (io >= k->vtable_size)
1785                                         continue;
1786                         }
1787                                 
1788                         for (l = 0; l < ic->method.count; l++) {
1789                                 MonoMethod *im = ic->methods [l];                                               
1790                                 MonoClass *k1;
1791
1792                                 g_assert (io + l <= max_vtsize);
1793
1794                                 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1795                                         continue;
1796                                         
1797                                 for (k1 = class; k1; k1 = k1->parent) {
1798                                         for (j = 0; j < k1->method.count; ++j) {
1799                                                 MonoMethod *cm = k1->methods [j];
1800
1801                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
1802                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
1803                                                         continue;
1804                                                 
1805                                                 if (!strcmp(cm->name, im->name) && 
1806                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1807
1808                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1809                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1810                                                                 mono_secman_inheritancedemand_method (cm, im);
1811                                                         }
1812
1813                                                         g_assert (io + l <= max_vtsize);
1814                                                         vtable [io + l] = cm;
1815                                                         break;
1816                                                 }
1817                                                 
1818                                         }
1819                                         g_assert (io + l <= max_vtsize);
1820                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
1821                                                 break;
1822                                 }
1823                         }
1824
1825                         for (l = 0; l < ic->method.count; l++) {
1826                                 MonoMethod *im = ic->methods [l];                                               
1827                                 char *qname, *fqname, *cname, *the_cname;
1828                                 MonoClass *k1;
1829                                 
1830                                 if (vtable [io + l])
1831                                         continue;
1832
1833                                 if (pic) {
1834                                         the_cname = mono_type_get_name_full (&pic->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
1835                                         cname = the_cname;
1836                                 } else {
1837                                         the_cname = NULL;
1838                                         cname = (char*)ic->name;
1839                                 }
1840                                         
1841                                 qname = g_strconcat (cname, ".", im->name, NULL);
1842                                 if (ic->name_space && ic->name_space [0])
1843                                         fqname = g_strconcat (ic->name_space, ".", cname, ".", im->name, NULL);
1844                                 else
1845                                         fqname = NULL;
1846
1847                                 for (k1 = class; k1; k1 = k1->parent) {
1848                                         for (j = 0; j < k1->method.count; ++j) {
1849                                                 MonoMethod *cm = k1->methods [j];
1850
1851                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1852                                                         continue;
1853
1854                                                 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
1855                                                     mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (im))) {
1856
1857                                                         /* CAS - SecurityAction.InheritanceDemand on interface */
1858                                                         if (security_enabled && (im->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1859                                                                 mono_secman_inheritancedemand_method (cm, im);
1860                                                         }
1861
1862                                                         g_assert (io + l <= max_vtsize);
1863                                                         vtable [io + l] = cm;
1864                                                         break;
1865                                                 }
1866                                         }
1867                                 }
1868                                 g_free (the_cname);
1869                                 g_free (qname);
1870                                 g_free (fqname);
1871                         }
1872
1873                         
1874                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
1875                                 for (l = 0; l < ic->method.count; l++) {
1876                                         char *msig;
1877                                         MonoMethod *im = ic->methods [l];
1878                                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
1879                                                         continue;
1880                                         g_assert (io + l <= max_vtsize);
1881
1882                                         /* 
1883                                          * If one of our parents already implements this interface
1884                                          * we can inherit the implementation.
1885                                          */
1886                                         if (!(vtable [io + l])) {
1887                                                 MonoClass *parent = class->parent;
1888
1889                                                 if ((ic->interface_id <= parent->max_interface_id) && 
1890                                                         (parent->interface_offsets [ic->interface_id] != -1) &&
1891                                                         parent->vtable)
1892                                                         vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
1893                                         }
1894
1895                                         if (!(vtable [io + l])) {
1896                                                 for (j = 0; j < onum; ++j) {
1897                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
1898                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
1899                                                 }
1900                                                 msig = mono_signature_get_desc (mono_method_signature (im), FALSE);
1901                                                 printf ("no implementation for interface method %s::%s(%s) in class %s.%s\n",
1902                                                         mono_type_get_name (&ic->byval_arg), im->name, msig, class->name_space, class->name);
1903                                                 g_free (msig);
1904                                                 for (j = 0; j < class->method.count; ++j) {
1905                                                         MonoMethod *cm = class->methods [j];
1906                                                         msig = mono_signature_get_desc (mono_method_signature (cm), TRUE);
1907                                                         
1908                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
1909                                                         g_free (msig);
1910                                                 }
1911                                                 g_assert_not_reached ();
1912                                         }
1913                                 }
1914                         }
1915                 
1916                         for (l = 0; l < ic->method.count; l++) {
1917                                 MonoMethod *im = vtable [io + l];
1918
1919                                 if (im) {
1920                                         g_assert (io + l <= max_vtsize);
1921                                         if (im->slot < 0) {
1922                                                 /* FIXME: why do we need this ? */
1923                                                 im->slot = io + l;
1924                                                 /* g_assert_not_reached (); */
1925                                         }
1926                                 }
1927                         }
1928                 }
1929                 if (ifaces)
1930                         g_ptr_array_free (ifaces, TRUE);
1931         } 
1932
1933         for (i = 0; i < class->method.count; ++i) {
1934                 MonoMethod *cm;
1935                
1936                 cm = class->methods [i];
1937                 
1938                 /*
1939                  * Non-virtual method have no place in the vtable.
1940                  * This also catches static methods (since they are not virtual).
1941                  */
1942                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
1943                         continue;
1944                 
1945                 /*
1946                  * If the method is REUSE_SLOT, we must check in the
1947                  * base class for a method to override.
1948                  */
1949                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
1950                         int slot = -1;
1951                         for (k = class->parent; k ; k = k->parent) {
1952                                 int j;
1953                                 for (j = 0; j < k->method.count; ++j) {
1954                                         MonoMethod *m1 = k->methods [j];
1955                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
1956                                                 continue;
1957                                         if (!strcmp(cm->name, m1->name) && 
1958                                             mono_metadata_signature_equal (mono_method_signature (cm), mono_method_signature (m1))) {
1959
1960                                                 /* CAS - SecurityAction.InheritanceDemand */
1961                                                 if (security_enabled && (m1->flags & METHOD_ATTRIBUTE_HAS_SECURITY)) {
1962                                                         mono_secman_inheritancedemand_method (cm, m1);
1963                                                 }
1964
1965                                                 slot = k->methods [j]->slot;
1966                                                 g_assert (cm->slot < max_vtsize);
1967                                                 if (!override_map)
1968                                                         override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1969                                                 g_hash_table_insert (override_map, m1, cm);
1970                                                 break;
1971                                         }
1972                                 }
1973                                 if (slot >= 0) 
1974                                         break;
1975                         }
1976                         if (slot >= 0)
1977                                 cm->slot = slot;
1978                 }
1979
1980                 if (cm->slot < 0)
1981                         cm->slot = cur_slot++;
1982
1983                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
1984                         vtable [cm->slot] = cm;
1985         }
1986
1987         /* override non interface methods */
1988         for (i = 0; i < onum; i++) {
1989                 MonoMethod *decl = overrides [i*2];
1990                 if (!MONO_CLASS_IS_INTERFACE (decl->klass)) {
1991                         g_assert (decl->slot != -1);
1992                         vtable [decl->slot] = overrides [i*2 + 1];
1993                         overrides [i * 2 + 1]->slot = decl->slot;
1994                         if (!override_map)
1995                                 override_map = g_hash_table_new (mono_aligned_addr_hash, NULL);
1996                         g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
1997                 }
1998         }
1999
2000         /*
2001          * If a method occupies more than one place in the vtable, and it is
2002          * overriden, then change the other occurances too.
2003          */
2004         if (override_map) {
2005                 for (i = 0; i < max_vtsize; ++i)
2006                         if (vtable [i]) {
2007                                 MonoMethod *cm = g_hash_table_lookup (override_map, vtable [i]);
2008                                 if (cm)
2009                                         vtable [i] = cm;
2010                         }
2011
2012                 g_hash_table_destroy (override_map);
2013         }
2014
2015         if (class->generic_class) {
2016                 MonoClass *gklass = class->generic_class->container_class;
2017
2018                 mono_class_init (gklass);
2019
2020                 class->vtable_size = MAX (gklass->vtable_size, cur_slot);
2021         } else
2022                 class->vtable_size = cur_slot;
2023
2024         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
2025         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
2026
2027         if (mono_print_vtable) {
2028                 int icount = 0;
2029
2030                 for (i = 0; i <= max_iid; i++)
2031                         if (class->interface_offsets [i] != -1)
2032                                 icount++;
2033
2034                 printf ("VTable %s (vtable entries = %d, interfaces = %d)\n", mono_type_full_name (&class->byval_arg), 
2035                         class->vtable_size, icount); 
2036
2037                 for (i = 0; i < class->vtable_size; ++i) {
2038                         MonoMethod *cm;
2039                
2040                         cm = vtable [i];
2041                         if (cm) {
2042                                 printf ("  slot assigned: %03d, slot index: %03d %s\n", i, cm->slot,
2043                                         mono_method_full_name (cm, TRUE));
2044                         }
2045                 }
2046
2047
2048                 if (icount) {
2049                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
2050                                 class->name, max_iid);
2051         
2052                         for (i = 0; i < class->interface_count; i++) {
2053                                 ic = class->interfaces [i];
2054                                 printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
2055                                         class->interface_offsets [ic->interface_id],
2056                                         ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2057                         }
2058
2059                         for (k = class->parent; k ; k = k->parent) {
2060                                 for (i = 0; i < k->interface_count; i++) {
2061                                         ic = k->interfaces [i]; 
2062                                         printf ("  slot offset: %03d, method count: %03d, iid: %03d %s\n",  
2063                                                 class->interface_offsets [ic->interface_id],
2064                                                 ic->method.count, ic->interface_id, mono_type_full_name (&ic->byval_arg));
2065                                 }
2066                         }
2067                 }
2068         }
2069 }
2070
2071 /**
2072  * mono_class_init:
2073  * @class: the class to initialize
2074  *
2075  * compute the instance_size, class_size and other infos that cannot be 
2076  * computed at mono_class_get() time. Also compute a generic vtable and 
2077  * the method slot numbers. We use this infos later to create a domain
2078  * specific vtable.  
2079  */
2080 void
2081 mono_class_init (MonoClass *class)
2082 {
2083         int i;
2084         static MonoMethod *default_ghc = NULL;
2085         static MonoMethod *default_finalize = NULL;
2086         static int finalize_slot = -1;
2087         static int ghc_slot = -1;
2088         MonoCachedClassInfo cached_info;
2089         gboolean has_cached_info;
2090
2091         g_assert (class);
2092
2093         if (class->inited)
2094                 return;
2095
2096         /*g_print ("Init class %s\n", class->name);*/
2097
2098         /* We do everything inside the lock to prevent races */
2099         mono_loader_lock ();
2100
2101         if (class->inited) {
2102                 mono_loader_unlock ();
2103                 /* Somebody might have gotten in before us */
2104                 return;
2105         }
2106
2107         if (class->init_pending) {
2108                 mono_loader_unlock ();
2109                 /* this indicates a cyclic dependency */
2110                 g_error ("pending init %s.%s\n", class->name_space, class->name);
2111         }
2112
2113         class->init_pending = 1;
2114
2115         /* CAS - SecurityAction.InheritanceDemand */
2116         if (mono_is_security_manager_active () && class->parent && (class->parent->flags & TYPE_ATTRIBUTE_HAS_SECURITY)) {
2117                 mono_secman_inheritancedemand_class (class, class->parent);
2118         }
2119
2120         if (mono_debugger_start_class_init_func)
2121                 mono_debugger_start_class_init_func (class);
2122
2123         mono_stats.initialized_class_count++;
2124
2125         if (class->generic_class && !class->generic_class->is_dynamic) {
2126                 MonoInflatedGenericClass *gclass;
2127                 MonoClass *gklass;
2128
2129                 gclass = mono_get_inflated_generic_class (class->generic_class);
2130                 gklass = gclass->generic_class.container_class;
2131
2132                 mono_stats.generic_class_count++;
2133
2134                 class->method = gklass->method;
2135                 class->field = gklass->field;
2136
2137                 mono_class_init (gklass);
2138                 mono_class_setup_methods (gklass);
2139                 mono_class_setup_properties (gklass);
2140
2141                 if (MONO_CLASS_IS_INTERFACE (class))
2142                         class->interface_id = mono_get_unique_iid (class);
2143
2144                 g_assert (class->method.count == gklass->method.count);
2145                 class->methods = g_new0 (MonoMethod *, class->method.count);
2146
2147                 for (i = 0; i < class->method.count; i++) {
2148                         MonoMethod *inflated = mono_class_inflate_generic_method_full (
2149                                 gklass->methods [i], class, gclass->generic_class.context);
2150
2151                         class->methods [i] = mono_get_inflated_method (inflated);
2152                 }
2153
2154                 class->property = gklass->property;
2155                 class->properties = g_new0 (MonoProperty, class->property.count);
2156
2157                 for (i = 0; i < class->property.count; i++) {
2158                         MonoProperty *prop = &class->properties [i];
2159
2160                         *prop = gklass->properties [i];
2161
2162                         if (prop->get)
2163                                 prop->get = mono_class_inflate_generic_method_full (
2164                                         prop->get, class, gclass->generic_class.context);
2165                         if (prop->set)
2166                                 prop->set = mono_class_inflate_generic_method_full (
2167                                         prop->set, class, gclass->generic_class.context);
2168
2169                         prop->parent = class;
2170                 }
2171
2172                 g_assert (class->interface_count == gklass->interface_count);
2173         }
2174
2175         if (class->parent && !class->parent->inited)
2176                 mono_class_init (class->parent);
2177
2178         has_cached_info = mono_class_get_cached_class_info (class, &cached_info);
2179
2180         if (!class->generic_class && (!has_cached_info || (has_cached_info && cached_info.has_nested_classes))) {
2181                 i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
2182                 while (i) {
2183                         MonoClass* nclass;
2184                         guint32 cols [MONO_NESTED_CLASS_SIZE];
2185                         mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
2186                         nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
2187                         class->nested_classes = g_list_prepend (class->nested_classes, nclass);
2188
2189                         i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
2190                 }
2191         }
2192
2193         /*
2194          * Computes the size used by the fields, and their locations
2195          */
2196         if (has_cached_info) {
2197                 class->instance_size = cached_info.instance_size;
2198                 class->class_size = cached_info.class_size;
2199                 class->packing_size = cached_info.packing_size;
2200                 class->min_align = cached_info.min_align;
2201                 class->blittable = cached_info.blittable;
2202                 class->has_references = cached_info.has_references;
2203                 class->has_static_refs = cached_info.has_static_refs;
2204         }
2205         else
2206                 if (!class->size_inited)
2207                         mono_class_setup_fields (class);
2208
2209         /* initialize method pointers */
2210         if (class->rank) {
2211                 MonoMethod *ctor;
2212                 MonoMethodSignature *sig;
2213                 class->method.count = class->rank > 1? 2: 1;
2214                 sig = mono_metadata_signature_alloc (class->image, class->rank);
2215                 sig->ret = &mono_defaults.void_class->byval_arg;
2216                 sig->pinvoke = TRUE;
2217                 for (i = 0; i < class->rank; ++i)
2218                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
2219
2220                 ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
2221                 ctor->klass = class;
2222                 ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2223                 ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2224                 ctor->signature = sig;
2225                 ctor->name = ".ctor";
2226                 ctor->slot = -1;
2227                 class->methods = g_new (MonoMethod*, class->method.count);
2228                 class->methods [0] = ctor;
2229                 if (class->rank > 1) {
2230                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
2231                         sig->ret = &mono_defaults.void_class->byval_arg;
2232                         sig->pinvoke = TRUE;
2233                         for (i = 0; i < class->rank * 2; ++i)
2234                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
2235
2236                         ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
2237                         ctor->klass = class;
2238                         ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
2239                         ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
2240                         ctor->signature = sig;
2241                         ctor->name = ".ctor";
2242                         ctor->slot = -1;
2243                         class->methods [1] = ctor;
2244                 }
2245         }
2246
2247         mono_class_setup_supertypes (class);
2248
2249         if (!default_ghc) {
2250                 if (class == mono_defaults.object_class) { 
2251                         mono_class_setup_vtable (class);                       
2252                         for (i = 0; i < class->vtable_size; ++i) {
2253                                 MonoMethod *cm = class->vtable [i];
2254                
2255                                 if (!strcmp (cm->name, "GetHashCode")) {
2256                                         ghc_slot = i;
2257                                         break;
2258                                 }
2259                         }
2260
2261                         g_assert (ghc_slot > 0);
2262
2263                         default_ghc = class->vtable [ghc_slot];
2264                 }
2265         }
2266
2267         if (!default_finalize) {
2268                 if (class == mono_defaults.object_class) { 
2269                         mono_class_setup_vtable (class);                       
2270                         for (i = 0; i < class->vtable_size; ++i) {
2271                                 MonoMethod *cm = class->vtable [i];
2272                
2273                                 if (!strcmp (cm->name, "Finalize")) {
2274                                         finalize_slot = i;
2275                                         break;
2276                                 }
2277                         }
2278
2279                         g_assert (finalize_slot > 0);
2280
2281                         default_finalize = class->vtable [finalize_slot];
2282                 }
2283         }
2284
2285         /*
2286          * If possible, avoid the creation of the generic vtable by requesting
2287          * cached info from the runtime.
2288          */
2289         if (has_cached_info) {
2290                 guint32 cur_slot = 0;
2291
2292                 class->vtable_size = cached_info.vtable_size;
2293                 class->has_finalize = cached_info.has_finalize;
2294                 class->ghcimpl = cached_info.ghcimpl;
2295                 class->has_cctor = cached_info.has_cctor;
2296
2297                 if (class->parent) {
2298                         mono_class_init (class->parent);
2299                         cur_slot = class->parent->vtable_size;
2300                 }
2301
2302                 setup_interface_offsets (class, cur_slot);
2303         }
2304         else {
2305                 mono_class_setup_vtable (class);
2306         
2307                 class->ghcimpl = 1;
2308                 if (class->parent) { 
2309                         MonoMethod *cmethod = class->vtable [ghc_slot];
2310                         if (cmethod->is_inflated)
2311                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2312                         if (cmethod == default_ghc) {
2313                                 class->ghcimpl = 0;
2314                         }
2315                 }
2316
2317                 /* Object::Finalize should have empty implemenatation */
2318                 class->has_finalize = 0;
2319                 if (class->parent) { 
2320                         MonoMethod *cmethod = class->vtable [finalize_slot];
2321                         if (cmethod->is_inflated)
2322                                 cmethod = ((MonoMethodInflated*)cmethod)->declaring;
2323                         if (cmethod != default_finalize) {
2324                                 class->has_finalize = 1;
2325                         }
2326                 }
2327
2328                 for (i = 0; i < class->method.count; ++i) {
2329                         MonoMethod *method = class->methods [i];
2330                         if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
2331                                 (strcmp (".cctor", method->name) == 0)) {
2332                                 class->has_cctor = 1;
2333                                 break;
2334                         }
2335                 }
2336         }
2337
2338         class->inited = 1;
2339         class->init_pending = 0;
2340         
2341         mono_loader_unlock ();
2342
2343         if (MONO_CLASS_IS_INTERFACE (class)) {
2344                 /* 
2345                  * class->interface_offsets is needed for the castclass/isinst code, so
2346                  * we have to setup them for interfaces, too.
2347                  */
2348                 setup_interface_offsets (class, 0);
2349         }
2350
2351         if (mono_debugger_class_init_func)
2352                 mono_debugger_class_init_func (class);
2353 }
2354
2355 /*
2356  * LOCKING: this assumes the loader lock is held
2357  */
2358 void
2359 mono_class_setup_mono_type (MonoClass *class)
2360 {
2361         const char *name = class->name;
2362         const char *nspace = class->name_space;
2363
2364         class->this_arg.byref = 1;
2365         class->this_arg.data.klass = class;
2366         class->this_arg.type = MONO_TYPE_CLASS;
2367         class->byval_arg.data.klass = class;
2368         class->byval_arg.type = MONO_TYPE_CLASS;
2369
2370         if (!strcmp (nspace, "System")) {
2371                 if (!strcmp (name, "ValueType")) {
2372                         /*
2373                          * do not set the valuetype bit for System.ValueType.
2374                          * class->valuetype = 1;
2375                          */
2376                         class->blittable = TRUE;
2377                 } else if (!strcmp (name, "Enum")) {
2378                         /*
2379                          * do not set the valuetype bit for System.Enum.
2380                          * class->valuetype = 1;
2381                          */
2382                         class->valuetype = 0;
2383                         class->enumtype = 0;
2384                 } else if (!strcmp (name, "Object")) {
2385                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
2386                 } else if (!strcmp (name, "String")) {
2387                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
2388                 } else if (!strcmp (name, "TypedReference")) {
2389                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
2390                 }
2391         }
2392         
2393         if (class->valuetype) {
2394                 int t = MONO_TYPE_VALUETYPE;
2395                 if (!strcmp (nspace, "System")) {
2396                         switch (*name) {
2397                         case 'B':
2398                                 if (!strcmp (name, "Boolean")) {
2399                                         t = MONO_TYPE_BOOLEAN;
2400                                 } else if (!strcmp(name, "Byte")) {
2401                                         t = MONO_TYPE_U1;
2402                                         class->blittable = TRUE;                                                
2403                                 }
2404                                 break;
2405                         case 'C':
2406                                 if (!strcmp (name, "Char")) {
2407                                         t = MONO_TYPE_CHAR;
2408                                 }
2409                                 break;
2410                         case 'D':
2411                                 if (!strcmp (name, "Double")) {
2412                                         t = MONO_TYPE_R8;
2413                                         class->blittable = TRUE;                                                
2414                                 }
2415                                 break;
2416                         case 'I':
2417                                 if (!strcmp (name, "Int32")) {
2418                                         t = MONO_TYPE_I4;
2419                                         class->blittable = TRUE;
2420                                 } else if (!strcmp(name, "Int16")) {
2421                                         t = MONO_TYPE_I2;
2422                                         class->blittable = TRUE;
2423                                 } else if (!strcmp(name, "Int64")) {
2424                                         t = MONO_TYPE_I8;
2425                                         class->blittable = TRUE;
2426                                 } else if (!strcmp(name, "IntPtr")) {
2427                                         t = MONO_TYPE_I;
2428                                         class->blittable = TRUE;
2429                                 }
2430                                 break;
2431                         case 'S':
2432                                 if (!strcmp (name, "Single")) {
2433                                         t = MONO_TYPE_R4;
2434                                         class->blittable = TRUE;                                                
2435                                 } else if (!strcmp(name, "SByte")) {
2436                                         t = MONO_TYPE_I1;
2437                                         class->blittable = TRUE;
2438                                 }
2439                                 break;
2440                         case 'U':
2441                                 if (!strcmp (name, "UInt32")) {
2442                                         t = MONO_TYPE_U4;
2443                                         class->blittable = TRUE;
2444                                 } else if (!strcmp(name, "UInt16")) {
2445                                         t = MONO_TYPE_U2;
2446                                         class->blittable = TRUE;
2447                                 } else if (!strcmp(name, "UInt64")) {
2448                                         t = MONO_TYPE_U8;
2449                                         class->blittable = TRUE;
2450                                 } else if (!strcmp(name, "UIntPtr")) {
2451                                         t = MONO_TYPE_U;
2452                                         class->blittable = TRUE;
2453                                 }
2454                                 break;
2455                         case 'T':
2456                                 if (!strcmp (name, "TypedReference")) {
2457                                         t = MONO_TYPE_TYPEDBYREF;
2458                                         class->blittable = TRUE;
2459                                 }
2460                                 break;
2461                         case 'V':
2462                                 if (!strcmp (name, "Void")) {
2463                                         t = MONO_TYPE_VOID;
2464                                 }
2465                                 break;
2466                         default:
2467                                 break;
2468                         }
2469                 }
2470                 class->this_arg.type = class->byval_arg.type = t;
2471         }
2472
2473         if (MONO_CLASS_IS_INTERFACE (class))
2474                 class->interface_id = mono_get_unique_iid (class);
2475
2476 }
2477
2478 /*
2479  * LOCKING: this assumes the loader lock is held
2480  */
2481 void
2482 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
2483 {
2484         gboolean system_namespace;
2485
2486         system_namespace = !strcmp (class->name_space, "System");
2487
2488         /* if root of the hierarchy */
2489         if (system_namespace && !strcmp (class->name, "Object")) {
2490                 class->parent = NULL;
2491                 class->instance_size = sizeof (MonoObject);
2492                 return;
2493         }
2494         if (!strcmp (class->name, "<Module>")) {
2495                 class->parent = NULL;
2496                 class->instance_size = 0;
2497                 return;
2498         }
2499
2500         if (!MONO_CLASS_IS_INTERFACE (class)) {
2501                 class->parent = parent;
2502
2503                 if (!parent)
2504                         g_assert_not_reached (); /* FIXME */
2505
2506                 if (parent->generic_class && !parent->name) {
2507                         /*
2508                          * If the parent is a generic instance, we may get
2509                          * called before it is fully initialized, especially
2510                          * before it has its name.
2511                          */
2512                         return;
2513                 }
2514
2515                 class->marshalbyref = parent->marshalbyref;
2516                 class->contextbound  = parent->contextbound;
2517                 class->delegate  = parent->delegate;
2518                 
2519                 if (system_namespace) {
2520                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
2521                                 class->marshalbyref = 1;
2522
2523                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
2524                                 class->contextbound  = 1;
2525
2526                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
2527                                 class->delegate  = 1;
2528                 }
2529
2530                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
2531                                                 (strcmp (class->parent->name_space, "System") == 0)))
2532                         class->valuetype = 1;
2533                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
2534                         class->valuetype = class->enumtype = 1;
2535                 }
2536                 /*class->enumtype = class->parent->enumtype; */
2537                 mono_class_setup_supertypes (class);
2538         } else {
2539                 class->parent = NULL;
2540         }
2541
2542 }
2543
2544 /*
2545  * LOCKING: this assumes the loader lock is held
2546  */
2547 void
2548 mono_class_setup_supertypes (MonoClass *class)
2549 {
2550         int ms;
2551
2552         if (class->supertypes)
2553                 return;
2554
2555         if (class->parent && !class->parent->supertypes)
2556                 mono_class_setup_supertypes (class->parent);
2557         if (class->parent)
2558                 class->idepth = class->parent->idepth + 1;
2559         else
2560                 class->idepth = 1;
2561
2562         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
2563         class->supertypes = g_new0 (MonoClass *, ms);
2564
2565         if (class->parent) {
2566                 class->supertypes [class->idepth - 1] = class;
2567                 memcpy (class->supertypes, class->parent->supertypes, class->parent->idepth * sizeof (gpointer));
2568         } else {
2569                 class->supertypes [0] = class;
2570         }
2571 }       
2572
2573 MonoGenericInst *
2574 mono_get_shared_generic_inst (MonoGenericContainer *container)
2575 {
2576         MonoGenericInst *nginst;
2577         int i;
2578
2579         nginst = g_new0 (MonoGenericInst, 1);
2580         nginst->type_argc = container->type_argc;
2581         nginst->type_argv = g_new0 (MonoType *, nginst->type_argc);
2582         nginst->is_reference = 1;
2583         nginst->is_open = 1;
2584
2585         for (i = 0; i < nginst->type_argc; i++) {
2586                 MonoType *t = g_new0 (MonoType, 1);
2587
2588                 t->type = container->is_method ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2589                 t->data.generic_param = &container->type_params [i];
2590
2591                 nginst->type_argv [i] = t;
2592         }
2593
2594         return mono_metadata_lookup_generic_inst (nginst);
2595 }
2596
2597 /*
2598  * In preparation for implementing shared code.
2599  */
2600 MonoGenericClass *
2601 mono_get_shared_generic_class (MonoGenericContainer *container, gboolean is_dynamic)
2602 {
2603         MonoInflatedGenericClass *igclass;
2604         MonoGenericClass *gclass;
2605
2606         if (is_dynamic) {
2607                 MonoDynamicGenericClass *dgclass = g_new0 (MonoDynamicGenericClass, 1);
2608                 igclass = &dgclass->generic_class;
2609                 gclass = &igclass->generic_class;
2610                 gclass->is_inflated = 1;
2611                 gclass->is_dynamic = 1;
2612         } else {
2613                 igclass = g_new0 (MonoInflatedGenericClass, 1);
2614                 gclass = &igclass->generic_class;
2615                 gclass->is_inflated = 1;
2616         }
2617
2618         gclass->context = &container->context;
2619         gclass->container_class = container->klass;
2620         gclass->inst = mono_get_shared_generic_inst (container);
2621
2622         if (!is_dynamic) {
2623                 MonoGenericClass *cached = mono_metadata_lookup_generic_class (gclass);
2624
2625                 if (cached) {
2626                         g_free (gclass);
2627                         return cached;
2628                 }
2629         }
2630
2631         igclass->klass = container->klass;
2632
2633         return gclass;
2634 }
2635
2636 /**
2637  * @image: context where the image is created
2638  * @type_token:  typedef token
2639  */
2640 static MonoClass *
2641 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
2642 {
2643         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
2644         MonoClass *class, *parent = NULL;
2645         guint32 cols [MONO_TYPEDEF_SIZE];
2646         guint32 cols_next [MONO_TYPEDEF_SIZE];
2647         guint tidx = mono_metadata_token_index (type_token);
2648         MonoGenericContext *context = NULL;
2649         const char *name, *nspace;
2650         guint icount = 0; 
2651         MonoClass **interfaces;
2652         guint32 field_last, method_last;
2653         guint32 nesting_tokeen;
2654
2655         mono_loader_lock ();
2656
2657         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
2658                 mono_loader_unlock ();
2659                 return class;
2660         }
2661
2662         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
2663
2664         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
2665         
2666         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2667         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2668
2669         class = g_malloc0 (sizeof (MonoClass));
2670
2671         class->name = name;
2672         class->name_space = nspace;
2673
2674         class->image = image;
2675         class->type_token = type_token;
2676         class->flags = cols [MONO_TYPEDEF_FLAGS];
2677
2678         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
2679
2680         /*
2681          * Check whether we're a generic type definition.
2682          */
2683         class->generic_container = mono_metadata_load_generic_params (image, class->type_token, NULL);
2684         if (class->generic_container) {
2685                 class->generic_container->klass = class;
2686                 context = &class->generic_container->context;
2687
2688                 context->gclass = mono_get_shared_generic_class (context->container, FALSE);
2689         }
2690
2691         if (cols [MONO_TYPEDEF_EXTENDS]) {
2692                 parent = mono_class_get_full (
2693                         image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]), context);
2694         }
2695
2696         /* do this early so it's available for interfaces in setup_mono_type () */
2697         if ((nesting_tokeen = mono_metadata_nested_in_typedef (image, type_token)))
2698                 class->nested_in = mono_class_create_from_typedef (image, nesting_tokeen);
2699
2700         mono_class_setup_parent (class, parent);
2701
2702         mono_class_setup_mono_type (class);
2703
2704         if (!class->enumtype) {
2705                 mono_metadata_interfaces_from_typedef_full (image, type_token, &interfaces, &icount, context);
2706
2707                 class->interfaces = interfaces;
2708                 class->interface_count = icount;
2709         }
2710
2711         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
2712                 class->unicode = 1;
2713         /* fixme: maybe we must set this on windows 
2714         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
2715                 class->unicode = 1;
2716         */
2717
2718         class->cast_class = class->element_class = class;
2719
2720         /*g_print ("Load class %s\n", name);*/
2721
2722         /*
2723          * Compute the field and method lists
2724          */
2725         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
2726         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
2727
2728         if (tt->rows > tidx){           
2729                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
2730                 field_last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
2731                 method_last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
2732         } else {
2733                 field_last  = image->tables [MONO_TABLE_FIELD].rows;
2734                 method_last = image->tables [MONO_TABLE_METHOD].rows;
2735         }
2736
2737         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
2738             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
2739                 class->field.count = field_last - class->field.first;
2740         else
2741                 class->field.count = 0;
2742
2743         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
2744                 class->method.count = method_last - class->method.first;
2745         else
2746                 class->method.count = 0;
2747
2748         /* reserve space to store vector pointer in arrays */
2749         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
2750                 class->instance_size += 2 * sizeof (gpointer);
2751                 g_assert (class->field.count == 0);
2752         }
2753
2754         if (class->enumtype) {
2755                 class->enum_basetype = mono_class_find_enum_basetype (class);
2756                 class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
2757         }
2758
2759         /*
2760          * If we're a generic type definition, load the constraints.
2761          * We must do this after the class has been constructed to make certain recursive scenarios
2762          * work.
2763          */
2764         if (class->generic_container)
2765                 mono_metadata_load_generic_param_constraints (
2766                         image, type_token, class->generic_container);
2767
2768         mono_loader_unlock ();
2769
2770         return class;
2771 }
2772
2773 /** is klass Nullable<T>? */
2774 gboolean
2775 mono_class_is_nullable (MonoClass *klass)
2776 {
2777        return klass->generic_class != NULL &&
2778                klass->generic_class->container_class == mono_defaults.generic_nullable_class;
2779 }
2780
2781
2782 /** if klass is T? return T */
2783 MonoClass*
2784 mono_class_get_nullable_param (MonoClass *klass)
2785 {
2786        g_assert (mono_class_is_nullable (klass));
2787        return mono_class_from_mono_type (klass->generic_class->inst->type_argv [0]);
2788 }
2789
2790 /*
2791  * Create the `MonoClass' for an instantiation of a generic type.
2792  * We only do this if we actually need it.
2793  */
2794 static void
2795 mono_class_create_generic (MonoInflatedGenericClass *gclass)
2796 {
2797         MonoClass *klass, *gklass;
2798         int i;
2799
2800         if (gclass->is_initialized)
2801                 return;
2802         gclass->is_initialized = TRUE;
2803
2804         if (!gclass->klass)
2805                 gclass->klass = g_malloc0 (sizeof (MonoClass));
2806         klass = gclass->klass;
2807
2808         gklass = gclass->generic_class.container_class;
2809
2810         klass->nested_in = gklass->nested_in;
2811
2812         klass->name = gklass->name;
2813         klass->name_space = gklass->name_space;
2814         klass->image = gklass->image;
2815         klass->flags = gklass->flags;
2816         klass->type_token = gklass->type_token;
2817
2818         klass->generic_class = &gclass->generic_class;
2819
2820         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
2821         klass->this_arg.data.generic_class = klass->byval_arg.data.generic_class = &gclass->generic_class;
2822         klass->this_arg.byref = TRUE;
2823
2824         klass->cast_class = klass->element_class = klass;
2825
2826         if (mono_class_is_nullable (klass))
2827                 klass->cast_class = klass->element_class = mono_class_get_nullable_param (klass);
2828
2829         if (gclass->generic_class.is_dynamic) {
2830                 klass->instance_size = gklass->instance_size;
2831                 klass->class_size = gklass->class_size;
2832                 klass->size_inited = 1;
2833                 klass->inited = 1;
2834
2835                 klass->valuetype = gklass->valuetype;
2836
2837                 mono_class_setup_supertypes (klass);
2838         }
2839
2840         klass->interface_count = gklass->interface_count;
2841         klass->interfaces = g_new0 (MonoClass *, klass->interface_count);
2842         for (i = 0; i < klass->interface_count; i++) {
2843                 MonoType *it = &gklass->interfaces [i]->byval_arg;
2844                 MonoType *inflated = mono_class_inflate_generic_type (
2845                         it, gclass->generic_class.context);
2846                 klass->interfaces [i] = mono_class_from_mono_type (inflated);
2847         }
2848
2849         i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, 1);
2850         while (i) {
2851                 MonoClass* nclass;
2852                 guint32 cols [MONO_NESTED_CLASS_SIZE];
2853                 mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
2854                 nclass = mono_class_create_from_typedef (klass->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
2855                 klass->nested_classes = g_list_prepend (klass->nested_classes, nclass);
2856                 
2857                 i = mono_metadata_nesting_typedef (klass->image, gklass->type_token, i + 1);
2858         }
2859
2860         if (gclass->generic_class.is_dynamic) {
2861                 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) gclass;
2862
2863                 if (dgclass->parent)
2864                         klass->parent = mono_class_from_mono_type (dgclass->parent);
2865         } else if (gklass->parent) {
2866                 MonoType *inflated = mono_class_inflate_generic_type (
2867                         &gklass->parent->byval_arg, gclass->generic_class.context);
2868
2869                 klass->parent = mono_class_from_mono_type (inflated);
2870         }
2871
2872         if (klass->parent)
2873                 mono_class_setup_parent (klass, klass->parent);
2874
2875         if (MONO_CLASS_IS_INTERFACE (klass))
2876                 setup_interface_offsets (klass, 0);
2877 }
2878
2879 MonoClass *
2880 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
2881 {
2882         MonoClass *klass, **ptr;
2883         int count, pos, i;
2884
2885         if (param->pklass)
2886                 return param->pklass;
2887
2888         klass = param->pklass = g_new0 (MonoClass, 1);
2889
2890         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
2891                 ;
2892
2893         pos = 0;
2894         if ((count > 0) && !MONO_CLASS_IS_INTERFACE (param->constraints [0])) {
2895                 klass->parent = param->constraints [0];
2896                 pos++;
2897         } else if (param->flags & GENERIC_PARAMETER_ATTRIBUTE_VALUE_TYPE_CONSTRAINT)
2898                 klass->parent = mono_class_from_name (mono_defaults.corlib, "System", "ValueType");
2899         else
2900                 klass->parent = mono_defaults.object_class;
2901
2902         if (count - pos > 0) {
2903                 klass->interface_count = count - pos;
2904                 klass->interfaces = g_new0 (MonoClass *, count - pos);
2905                 for (i = pos; i < count; i++)
2906                         klass->interfaces [i - pos] = param->constraints [i];
2907         }
2908
2909         if (param->name)
2910                 klass->name = param->name;
2911         else
2912                 klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
2913
2914         klass->name_space = "";
2915
2916         if (image)
2917                 klass->image = image;
2918         else if (is_mvar && param->method && param->method->klass)
2919                 klass->image = param->method->klass->image;
2920         else if (param->owner && param->owner->klass)
2921                 klass->image = param->owner->klass->image;
2922         else
2923                 klass->image = mono_defaults.corlib;
2924
2925         klass->inited = TRUE;
2926         klass->cast_class = klass->element_class = klass;
2927         klass->enum_basetype = &klass->element_class->byval_arg;
2928         klass->flags = TYPE_ATTRIBUTE_PUBLIC;
2929
2930         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
2931         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
2932         klass->this_arg.byref = TRUE;
2933
2934         mono_class_setup_supertypes (klass);
2935
2936         return klass;
2937 }
2938
2939 MonoClass *
2940 mono_ptr_class_get (MonoType *type)
2941 {
2942         MonoClass *result;
2943         MonoClass *el_class;
2944         static GHashTable *ptr_hash = NULL;
2945
2946         mono_loader_lock ();
2947
2948         if (!ptr_hash)
2949                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
2950         el_class = mono_class_from_mono_type (type);
2951         if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
2952                 mono_loader_unlock ();
2953                 return result;
2954         }
2955         result = g_new0 (MonoClass, 1);
2956
2957         result->parent = NULL; /* no parent for PTR types */
2958         result->name_space = el_class->name_space;
2959         result->name = g_strdup_printf ("%s*", el_class->name);
2960         result->image = el_class->image;
2961         result->inited = TRUE;
2962         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2963         /* Can pointers get boxed? */
2964         result->instance_size = sizeof (gpointer);
2965         result->cast_class = result->element_class = el_class;
2966         result->enum_basetype = &result->element_class->byval_arg;
2967         result->blittable = TRUE;
2968
2969         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
2970         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
2971         result->this_arg.byref = TRUE;
2972
2973         mono_class_setup_supertypes (result);
2974
2975         g_hash_table_insert (ptr_hash, el_class, result);
2976
2977         mono_loader_unlock ();
2978
2979         return result;
2980 }
2981
2982 static MonoClass *
2983 mono_fnptr_class_get (MonoMethodSignature *sig)
2984 {
2985         MonoClass *result;
2986         static GHashTable *ptr_hash = NULL;
2987
2988         mono_loader_lock ();
2989
2990         if (!ptr_hash)
2991                 ptr_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
2992         
2993         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
2994                 mono_loader_unlock ();
2995                 return result;
2996         }
2997         result = g_new0 (MonoClass, 1);
2998
2999         result->parent = NULL; /* no parent for PTR types */
3000         result->name_space = "System";
3001         result->name = "MonoFNPtrFakeClass";
3002         result->image = NULL; /* need to fix... */
3003         result->inited = TRUE;
3004         result->flags = TYPE_ATTRIBUTE_CLASS; /* | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK); */
3005         /* Can pointers get boxed? */
3006         result->instance_size = sizeof (gpointer);
3007         result->cast_class = result->element_class = result;
3008         result->blittable = TRUE;
3009
3010         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
3011         result->this_arg.data.method = result->byval_arg.data.method = sig;
3012         result->this_arg.byref = TRUE;
3013         result->enum_basetype = &result->element_class->byval_arg;
3014         result->blittable = TRUE;
3015
3016         mono_class_setup_supertypes (result);
3017
3018         g_hash_table_insert (ptr_hash, sig, result);
3019
3020         mono_loader_unlock ();
3021
3022         return result;
3023 }
3024
3025 MonoClass *
3026 mono_class_from_mono_type (MonoType *type)
3027 {
3028         switch (type->type) {
3029         case MONO_TYPE_OBJECT:
3030                 return type->data.klass? type->data.klass: mono_defaults.object_class;
3031         case MONO_TYPE_VOID:
3032                 return type->data.klass? type->data.klass: mono_defaults.void_class;
3033         case MONO_TYPE_BOOLEAN:
3034                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
3035         case MONO_TYPE_CHAR:
3036                 return type->data.klass? type->data.klass: mono_defaults.char_class;
3037         case MONO_TYPE_I1:
3038                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
3039         case MONO_TYPE_U1:
3040                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
3041         case MONO_TYPE_I2:
3042                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
3043         case MONO_TYPE_U2:
3044                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
3045         case MONO_TYPE_I4:
3046                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
3047         case MONO_TYPE_U4:
3048                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
3049         case MONO_TYPE_I:
3050                 return type->data.klass? type->data.klass: mono_defaults.int_class;
3051         case MONO_TYPE_U:
3052                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
3053         case MONO_TYPE_I8:
3054                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
3055         case MONO_TYPE_U8:
3056                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
3057         case MONO_TYPE_R4:
3058                 return type->data.klass? type->data.klass: mono_defaults.single_class;
3059         case MONO_TYPE_R8:
3060                 return type->data.klass? type->data.klass: mono_defaults.double_class;
3061         case MONO_TYPE_STRING:
3062                 return type->data.klass? type->data.klass: mono_defaults.string_class;
3063         case MONO_TYPE_TYPEDBYREF:
3064                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
3065         case MONO_TYPE_ARRAY:
3066                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
3067         case MONO_TYPE_PTR:
3068                 return mono_ptr_class_get (type->data.type);
3069         case MONO_TYPE_FNPTR:
3070                 return mono_fnptr_class_get (type->data.method);
3071         case MONO_TYPE_SZARRAY:
3072                 return mono_array_class_get (type->data.klass, 1);
3073         case MONO_TYPE_CLASS:
3074         case MONO_TYPE_VALUETYPE:
3075                 return type->data.klass;
3076         case MONO_TYPE_GENERICINST: {
3077                 MonoInflatedGenericClass *gclass;
3078                 gclass = mono_get_inflated_generic_class (type->data.generic_class);
3079                 g_assert (gclass->klass);
3080                 return gclass->klass;
3081         }
3082         case MONO_TYPE_VAR:
3083                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, FALSE);
3084         case MONO_TYPE_MVAR:
3085                 return mono_class_from_generic_parameter (type->data.generic_param, NULL, TRUE);
3086         default:
3087                 g_warning ("implement me 0x%02x\n", type->type);
3088                 g_assert_not_reached ();
3089         }
3090         
3091         return NULL;
3092 }
3093
3094 /**
3095  * @image: context where the image is created
3096  * @type_spec:  typespec token
3097  */
3098 static MonoClass *
3099 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
3100 {
3101         return mono_class_from_mono_type (mono_type_create_from_typespec (image, type_spec));
3102 }
3103
3104 /**
3105  * mono_bounded_array_class_get:
3106  * @element_class: element class 
3107  * @rank: the dimension of the array class
3108  * @bounded: whenever the array has non-zero bounds
3109  *
3110  * Returns: a class object describing the array with element type @element_type and 
3111  * dimension @rank. 
3112  */
3113 MonoClass *
3114 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
3115 {
3116         MonoImage *image;
3117         MonoClass *class;
3118         MonoClass *parent = NULL;
3119         GSList *list, *rootlist;
3120         int nsize;
3121         char *name;
3122         gboolean corlib_type = FALSE;
3123
3124         g_assert (rank <= 255);
3125
3126         if (rank > 1)
3127                 /* bounded only matters for one-dimensional arrays */
3128                 bounded = FALSE;
3129
3130         image = eclass->image;
3131
3132         mono_loader_lock ();
3133
3134         if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
3135                 for (; list; list = list->next) {
3136                         class = list->data;
3137                         if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
3138                                 mono_loader_unlock ();
3139                                 return class;
3140                         }
3141                 }
3142         }
3143
3144         /* for the building corlib use System.Array from it */
3145         if (image->assembly && image->assembly->dynamic && image->assembly_name && strcmp (image->assembly_name, "mscorlib") == 0) {
3146                 parent = mono_class_from_name (image, "System", "Array");
3147                 corlib_type = TRUE;
3148         } else if (mono_defaults.generic_array_class) {
3149                 MonoType *inflated, **args;
3150
3151                 args = g_new0 (MonoType *, 1);
3152                 args [0] = &eclass->byval_arg;
3153
3154                 inflated = mono_class_bind_generic_parameters (
3155                         &mono_defaults.generic_array_class->byval_arg, 1, args);
3156                 parent = mono_class_from_mono_type (inflated);
3157
3158                 if (!parent->inited)
3159                         mono_class_init (parent);
3160         } else {
3161                 parent = mono_defaults.array_class;
3162                 if (!parent->inited)
3163                         mono_class_init (parent);
3164         }
3165
3166         class = g_malloc0 (sizeof (MonoClass));
3167
3168         class->image = image;
3169         class->name_space = eclass->name_space;
3170         nsize = strlen (eclass->name);
3171         name = g_malloc (nsize + 2 + rank);
3172         memcpy (name, eclass->name, nsize);
3173         name [nsize] = '[';
3174         if (rank > 1)
3175                 memset (name + nsize + 1, ',', rank - 1);
3176         name [nsize + rank] = ']';
3177         name [nsize + rank + 1] = 0;
3178         class->name = name;
3179         class->type_token = 0;
3180         /* all arrays are marked serializable and sealed, bug #42779 */
3181         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
3182                 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
3183         class->parent = parent;
3184         class->instance_size = mono_class_instance_size (class->parent);
3185         class->class_size = 0;
3186         mono_class_setup_supertypes (class);
3187         if (eclass->generic_class)
3188                 mono_class_init (eclass);
3189         if (!eclass->size_inited)
3190                 mono_class_setup_fields (eclass);
3191         class->has_references = MONO_TYPE_IS_REFERENCE (&eclass->byval_arg) || eclass->has_references? TRUE: FALSE;
3192
3193         class->rank = rank;
3194         
3195         if (eclass->enumtype)
3196                 class->cast_class = eclass->element_class;
3197         else
3198                 class->cast_class = eclass;
3199
3200         class->element_class = eclass;
3201
3202         if ((rank > 1) || bounded) {
3203                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
3204                 class->byval_arg.type = MONO_TYPE_ARRAY;
3205                 class->byval_arg.data.array = at;
3206                 at->eklass = eclass;
3207                 at->rank = rank;
3208                 /* FIXME: complete.... */
3209         } else {
3210                 class->byval_arg.type = MONO_TYPE_SZARRAY;
3211                 class->byval_arg.data.klass = eclass;
3212         }
3213         class->this_arg = class->byval_arg;
3214         class->this_arg.byref = 1;
3215         if (corlib_type) {
3216                 class->inited = 1;
3217         }
3218
3219         class->generic_container = eclass->generic_container;
3220
3221         list = g_slist_append (rootlist, class);
3222         g_hash_table_insert (image->array_cache, eclass, list);
3223
3224         mono_loader_unlock ();
3225
3226         return class;
3227 }
3228
3229 /**
3230  * mono_array_class_get:
3231  * @element_class: element class 
3232  * @rank: the dimension of the array class
3233  *
3234  * Returns: a class object describing the array with element type @element_type and 
3235  * dimension @rank. 
3236  */
3237 MonoClass *
3238 mono_array_class_get (MonoClass *eclass, guint32 rank)
3239 {
3240         return mono_bounded_array_class_get (eclass, rank, FALSE);
3241 }
3242
3243 /**
3244  * mono_class_instance_size:
3245  * @klass: a class 
3246  * 
3247  * Returns: the size of an object instance
3248  */
3249 gint32
3250 mono_class_instance_size (MonoClass *klass)
3251 {       
3252         if (!klass->size_inited)
3253                 mono_class_init (klass);
3254
3255         return klass->instance_size;
3256 }
3257
3258 /**
3259  * mono_class_min_align:
3260  * @klass: a class 
3261  * 
3262  * Returns: minimm alignment requirements 
3263  */
3264 gint32
3265 mono_class_min_align (MonoClass *klass)
3266 {       
3267         if (!klass->size_inited)
3268                 mono_class_init (klass);
3269
3270         return klass->min_align;
3271 }
3272
3273 /**
3274  * mono_class_value_size:
3275  * @klass: a class 
3276  *
3277  * This function is used for value types, and return the
3278  * space and the alignment to store that kind of value object.
3279  *
3280  * Returns: the size of a value of kind @klass
3281  */
3282 gint32
3283 mono_class_value_size      (MonoClass *klass, guint32 *align)
3284 {
3285         gint32 size;
3286
3287         /* fixme: check disable, because we still have external revereces to
3288          * mscorlib and Dummy Objects 
3289          */
3290         /*g_assert (klass->valuetype);*/
3291
3292         size = mono_class_instance_size (klass) - sizeof (MonoObject);
3293
3294         if (align)
3295                 *align = klass->min_align;
3296
3297         return size;
3298 }
3299
3300 /**
3301  * mono_class_data_size:
3302  * @klass: a class 
3303  * 
3304  * Returns: the size of the static class data
3305  */
3306 gint32
3307 mono_class_data_size (MonoClass *klass)
3308 {       
3309         if (!klass->inited)
3310                 mono_class_init (klass);
3311
3312         return klass->class_size;
3313 }
3314
3315 /*
3316  * Auxiliary routine to mono_class_get_field
3317  *
3318  * Takes a field index instead of a field token.
3319  */
3320 static MonoClassField *
3321 mono_class_get_field_idx (MonoClass *class, int idx)
3322 {
3323         mono_class_setup_fields_locking (class);
3324
3325         while (class) {
3326                 if (class->field.count) {
3327                         if ((idx >= class->field.first) && (idx < class->field.first + class->field.count)){
3328                                 return &class->fields [idx - class->field.first];
3329                         }
3330                 }
3331                 class = class->parent;
3332         }
3333         return NULL;
3334 }
3335
3336 /**
3337  * mono_class_get_field:
3338  * @class: the class to lookup the field.
3339  * @field_token: the field token
3340  *
3341  * Returns: A MonoClassField representing the type and offset of
3342  * the field, or a NULL value if the field does not belong to this
3343  * class.
3344  */
3345 MonoClassField *
3346 mono_class_get_field (MonoClass *class, guint32 field_token)
3347 {
3348         int idx = mono_metadata_token_index (field_token);
3349
3350         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
3351
3352         return mono_class_get_field_idx (class, idx - 1);
3353 }
3354
3355 /**
3356  * mono_class_get_field_from_name:
3357  * @klass: the class to lookup the field.
3358  * @name: the field name
3359  *
3360  * Search the class @klass and it's parents for a field with the name @name.
3361  * 
3362  * Returns: the MonoClassField pointer of the named field or NULL
3363  */
3364 MonoClassField *
3365 mono_class_get_field_from_name (MonoClass *klass, const char *name)
3366 {
3367         int i;
3368
3369         mono_class_setup_fields_locking (klass);
3370         while (klass) {
3371                 for (i = 0; i < klass->field.count; ++i) {
3372                         if (strcmp (name, klass->fields [i].name) == 0)
3373                                 return &klass->fields [i];
3374                 }
3375                 klass = klass->parent;
3376         }
3377         return NULL;
3378 }
3379
3380 /**
3381  * mono_class_get_field_token:
3382  * @field: the field we need the token of
3383  *
3384  * Get the token of a field. Note that the tokesn is only valid for the image
3385  * the field was loaded from. Don't use this function for fields in dynamic types.
3386  * 
3387  * Returns: the token representing the field in the image it was loaded from.
3388  */
3389 guint32
3390 mono_class_get_field_token (MonoClassField *field)
3391 {
3392         MonoClass *klass = field->parent;
3393         int i;
3394
3395         mono_class_setup_fields_locking (klass);
3396         while (klass) {
3397                 for (i = 0; i < klass->field.count; ++i) {
3398                         if (&klass->fields [i] == field)
3399                                 return mono_metadata_make_token (MONO_TABLE_FIELD, klass->field.first + i + 1);
3400                 }
3401                 klass = klass->parent;
3402         }
3403
3404         g_assert_not_reached ();
3405         return 0;
3406 }
3407
3408 guint32
3409 mono_class_get_event_token (MonoEvent *event)
3410 {
3411         MonoClass *klass = event->parent;
3412         int i;
3413
3414         while (klass) {
3415                 for (i = 0; i < klass->event.count; ++i) {
3416                         if (&klass->events [i] == event)
3417                                 return mono_metadata_make_token (MONO_TABLE_EVENT, klass->event.first + i + 1);
3418                 }
3419                 klass = klass->parent;
3420         }
3421
3422         g_assert_not_reached ();
3423         return 0;
3424 }
3425
3426 void *
3427 mono_vtable_get_static_field_data (MonoVTable *vt)
3428 {
3429         return vt->data;
3430 }
3431
3432 MonoProperty*
3433 mono_class_get_property_from_name (MonoClass *klass, const char *name)
3434 {
3435         while (klass) {
3436                 MonoProperty* p;
3437                 gpointer iter = NULL;
3438                 while ((p = mono_class_get_properties (klass, &iter))) {
3439                         if (! strcmp (name, p->name))
3440                                 return p;
3441                 }
3442                 klass = klass->parent;
3443         }
3444         return NULL;
3445 }
3446
3447 guint32
3448 mono_class_get_property_token (MonoProperty *prop)
3449 {
3450         MonoClass *klass = prop->parent;
3451         while (klass) {
3452                 MonoProperty* p;
3453                 int i = 0;
3454                 gpointer iter = NULL;
3455                 while ((p = mono_class_get_properties (klass, &iter))) {
3456                         if (&klass->properties [i] == prop)
3457                                 return mono_metadata_make_token (MONO_TABLE_PROPERTY, klass->property.first + i + 1);
3458                         
3459                         i ++;
3460                 }
3461                 klass = klass->parent;
3462         }
3463
3464         g_assert_not_reached ();
3465         return 0;
3466 }
3467
3468 char *
3469 mono_class_name_from_token (MonoImage *image, guint32 type_token)
3470 {
3471         const char *name, *nspace;
3472         if (image->dynamic)
3473                 return g_strdup_printf ("DynamicType 0x%08x", type_token);
3474         
3475         switch (type_token & 0xff000000){
3476         case MONO_TOKEN_TYPE_DEF: {
3477                 guint32 cols [MONO_TYPEDEF_SIZE];
3478                 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
3479                 guint tidx = mono_metadata_token_index (type_token);
3480
3481                 mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
3482                 name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3483                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3484                 if (strlen (nspace) == 0)
3485                         return g_strdup_printf ("%s", name);
3486                 else
3487                         return g_strdup_printf ("%s.%s", nspace, name);
3488         }
3489
3490         case MONO_TOKEN_TYPE_REF: {
3491                 guint32 cols [MONO_TYPEREF_SIZE];
3492                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
3493
3494                 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
3495                 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
3496                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
3497                 if (strlen (nspace) == 0)
3498                         return g_strdup_printf ("%s", name);
3499                 else
3500                         return g_strdup_printf ("%s.%s", nspace, name);
3501         }
3502                 
3503         case MONO_TOKEN_TYPE_SPEC:
3504                 return g_strdup_printf ("Typespec 0x%08x", type_token);
3505         default:
3506                 g_assert_not_reached ();
3507         }
3508
3509         return NULL;
3510 }
3511
3512 static char *
3513 mono_assembly_name_from_token (MonoImage *image, guint32 type_token)
3514 {
3515         if (image->dynamic)
3516                 return g_strdup_printf ("DynamicAssembly %s", image->name);
3517         
3518         switch (type_token & 0xff000000){
3519         case MONO_TOKEN_TYPE_DEF:
3520                 return mono_stringify_assembly_name (&image->assembly->aname);
3521                 break;
3522         case MONO_TOKEN_TYPE_REF: {
3523                 MonoAssemblyName aname;
3524                 guint32 cols [MONO_TYPEREF_SIZE];
3525                 MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
3526                 guint32 idx;
3527         
3528                 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
3529
3530                 idx = cols [MONO_TYPEREF_SCOPE] >> MONO_RESOLTION_SCOPE_BITS;
3531                 switch (cols [MONO_TYPEREF_SCOPE] & MONO_RESOLTION_SCOPE_MASK) {
3532                 case MONO_RESOLTION_SCOPE_MODULE:
3533                         /* FIXME: */
3534                         return g_strdup ("");
3535                 case MONO_RESOLTION_SCOPE_MODULEREF:
3536                         /* FIXME: */
3537                         return g_strdup ("");
3538                 case MONO_RESOLTION_SCOPE_TYPEREF:
3539                         /* FIXME: */
3540                         return g_strdup ("");
3541                 case MONO_RESOLTION_SCOPE_ASSEMBLYREF:
3542                         mono_assembly_get_assemblyref (image, idx - 1, &aname);
3543                         return mono_stringify_assembly_name (&aname);
3544                 default:
3545                         g_assert_not_reached ();
3546                 }
3547                 break;
3548         }
3549         case MONO_TOKEN_TYPE_SPEC:
3550                 /* FIXME: */
3551                 return g_strdup ("");
3552         default:
3553                 g_assert_not_reached ();
3554         }
3555
3556         return NULL;
3557 }
3558
3559 /**
3560  * mono_class_get:
3561  * @image: the image where the class resides
3562  * @type_token: the token for the class
3563  *
3564  * Returns: the MonoClass that represents @type_token in @image
3565  */
3566 MonoClass *
3567 mono_class_get (MonoImage *image, guint32 type_token)
3568 {
3569         MonoClass *class = NULL;
3570
3571         if (image->dynamic)
3572                 return mono_lookup_dynamic_token (image, type_token);
3573
3574         switch (type_token & 0xff000000){
3575         case MONO_TOKEN_TYPE_DEF:
3576                 class = mono_class_create_from_typedef (image, type_token);
3577                 break;          
3578         case MONO_TOKEN_TYPE_REF:
3579                 class = mono_class_from_typeref (image, type_token);
3580                 break;
3581         case MONO_TOKEN_TYPE_SPEC:
3582                 class = mono_class_create_from_typespec (image, type_token);
3583                 break;
3584         default:
3585                 g_warning ("unknown token type %x", type_token & 0xff000000);
3586                 g_assert_not_reached ();
3587         }
3588
3589         if (!class){
3590                 char *name = mono_class_name_from_token (image, type_token);
3591                 char *assembly = mono_assembly_name_from_token (image, type_token);
3592                 mono_loader_set_error_type_load (name, assembly);
3593         }
3594
3595         return class;
3596 }
3597
3598 MonoClass *
3599 mono_class_get_full (MonoImage *image, guint32 type_token, MonoGenericContext *context)
3600 {
3601         MonoClass *class = mono_class_get (image, type_token);
3602         if (class && context && (context->gclass || context->gmethod)) {
3603                 MonoType *inflated = inflate_generic_type (&class->byval_arg, context);
3604                 if (inflated)
3605                         class = mono_class_from_mono_type (inflated);
3606         }
3607         return class;
3608 }
3609
3610 typedef struct {
3611         gconstpointer key;
3612         gpointer value;
3613 } FindUserData;
3614
3615 static void
3616 find_nocase (gpointer key, gpointer value, gpointer user_data)
3617 {
3618         char *name = (char*)key;
3619         FindUserData *data = (FindUserData*)user_data;
3620
3621         if (!data->value && (g_strcasecmp (name, (char*)data->key) == 0))
3622                 data->value = value;
3623 }
3624
3625 /**
3626  * mono_class_from_name_case:
3627  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
3628  * @name_space: the type namespace
3629  * @name: the type short name.
3630  *
3631  * Obtains a MonoClass with a given namespace and a given name which
3632  * is located in the given MonoImage.   The namespace and name
3633  * lookups are case insensitive.
3634  *
3635  * You can also pass @NULL to the image, and that will lookup for
3636  * a type with the given namespace and name in all of the loaded
3637  * assemblies: notice that since there might be a name clash in this
3638  * case, passing @NULL is not encouraged if you need a precise type.
3639  *
3640  */
3641 MonoClass *
3642 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
3643 {
3644         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
3645         guint32 cols [MONO_TYPEDEF_SIZE];
3646         const char *n;
3647         const char *nspace;
3648         guint32 i, visib;
3649
3650         if (image->dynamic) {
3651                 guint32 token = 0;
3652                 FindUserData user_data;
3653
3654                 mono_loader_lock ();
3655
3656                 user_data.key = name_space;
3657                 user_data.value = NULL;
3658                 g_hash_table_foreach (image->name_cache, find_nocase, &user_data);
3659
3660                 if (user_data.value) {
3661                         GHashTable *nspace_table = (GHashTable*)user_data.value;
3662
3663                         user_data.key = name;
3664                         user_data.value = NULL;
3665
3666                         g_hash_table_foreach (nspace_table, find_nocase, &user_data);
3667                         
3668                         if (user_data.value)
3669                                 token = GPOINTER_TO_UINT (user_data.value);
3670                 }
3671
3672                 mono_loader_unlock ();
3673                 
3674                 if (token)
3675                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | token);
3676                 else
3677                         return NULL;
3678
3679         }
3680
3681         /* add a cache if needed */
3682         for (i = 1; i <= t->rows; ++i) {
3683                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
3684                 /* nested types are accessed from the nesting name */
3685                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
3686                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
3687                         continue;
3688                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
3689                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
3690                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
3691                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
3692         }
3693         return NULL;
3694 }
3695
3696 static MonoClass*
3697 return_nested_in (MonoClass *class, char *nested) {
3698         MonoClass *found;
3699         char *s = strchr (nested, '/');
3700         GList *tmp;
3701
3702         if (s) {
3703                 *s = 0;
3704                 s++;
3705         }
3706         for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
3707                 found = tmp->data;
3708                 if (strcmp (found->name, nested) == 0) {
3709                         if (s)
3710                                 return return_nested_in (found, s);
3711                         return found;
3712                 }
3713         }
3714         return NULL;
3715 }
3716
3717
3718 /**
3719  * mono_class_from_name:
3720  * @image: The MonoImage where the type is looked up in, or NULL for looking up in all loaded assemblies
3721  * @name_space: the type namespace
3722  * @name: the type short name.
3723  *
3724  * Obtains a MonoClass with a given namespace and a given name which
3725  * is located in the given MonoImage.   
3726  *
3727  * You can also pass `NULL' to the image, and that will lookup for
3728  * a type with the given namespace and name in all of the loaded
3729  * assemblies: notice that since there might be a name clash in this
3730  * case, passing NULL is not encouraged if you need a precise type.
3731  *
3732  */
3733 MonoClass *
3734 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
3735 {
3736         GHashTable *nspace_table;
3737         MonoImage *loaded_image;
3738         guint32 token = 0;
3739         MonoClass *class;
3740         char *nested;
3741         char buf [1024];
3742
3743         if ((nested = strchr (name, '/'))) {
3744                 int pos = nested - name;
3745                 int len = strlen (name);
3746                 if (len > 1023)
3747                         return NULL;
3748                 memcpy (buf, name, len + 1);
3749                 buf [pos] = 0;
3750                 nested = buf + pos + 1;
3751                 name = buf;
3752         }
3753
3754         mono_loader_lock ();
3755
3756         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
3757
3758         if (nspace_table)
3759                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
3760
3761         mono_loader_unlock ();
3762
3763         if (!token)
3764                 return NULL;
3765
3766         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
3767                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
3768                 guint32 cols [MONO_EXP_TYPE_SIZE];
3769                 guint32 idx, impl;
3770
3771                 idx = mono_metadata_token_index (token);
3772
3773                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
3774
3775                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
3776                 if ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE) {
3777                         loaded_image = mono_assembly_load_module (image->assembly, impl >> MONO_IMPLEMENTATION_BITS);
3778                         if (!loaded_image)
3779                                 return NULL;
3780                         class = mono_class_from_name (loaded_image, name_space, name);
3781                         if (nested)
3782                                 return return_nested_in (class, nested);
3783                         return class;
3784                 } else {
3785                         g_error ("not yet implemented");
3786                 }
3787         }
3788
3789         token = MONO_TOKEN_TYPE_DEF | token;
3790
3791         class = mono_class_get (image, token);
3792         if (nested)
3793                 return return_nested_in (class, nested);
3794         return class;
3795 }
3796
3797 gboolean
3798 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
3799                            gboolean check_interfaces)
3800 {
3801  again:
3802         g_assert (klassc->idepth > 0);
3803         if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && !MONO_CLASS_IS_INTERFACE (klass)) {
3804                 if ((klassc->interface_id <= klass->max_interface_id) &&
3805                         (klass->interface_offsets [klassc->interface_id] >= 0))
3806                         return TRUE;
3807         } else if (check_interfaces && MONO_CLASS_IS_INTERFACE (klassc) && MONO_CLASS_IS_INTERFACE (klass)) {
3808                 int i;
3809
3810                 for (i = 0; i < klass->interface_count; i ++) {
3811                         MonoClass *ic =  klass->interfaces [i];
3812                         if (ic == klassc)
3813                                 return TRUE;
3814                 }
3815         } else {
3816                 if (!MONO_CLASS_IS_INTERFACE (klass) && mono_class_has_parent (klass, klassc))
3817                         return TRUE;
3818         }
3819
3820         /* 
3821          * MS.NET thinks interfaces are a subclass of Object, so we think it as
3822          * well.
3823          */
3824         if (klassc == mono_defaults.object_class)
3825                 return TRUE;
3826
3827         if (klass->generic_class && klass->generic_class->is_dynamic) {
3828                 MonoDynamicGenericClass *dgclass = (MonoDynamicGenericClass *) klass->generic_class;
3829
3830                 if (!dgclass->parent)
3831                         return FALSE;
3832
3833                 if (mono_metadata_type_equal (dgclass->parent, &klassc->byval_arg))
3834                         return TRUE;
3835                 klass = mono_class_from_mono_type (dgclass->parent);
3836                 goto again;
3837         }
3838         
3839         return FALSE;
3840 }
3841
3842 gboolean
3843 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
3844 {
3845         if (!klass->inited)
3846                 mono_class_init (klass);
3847
3848         if (!oklass->inited)
3849                 mono_class_init (oklass);
3850
3851         if (MONO_CLASS_IS_INTERFACE (klass)) {
3852                 if ((oklass->byval_arg.type == MONO_TYPE_VAR) || (oklass->byval_arg.type == MONO_TYPE_MVAR))
3853                         return FALSE;
3854
3855                 /* interface_offsets might not be set for dynamic classes */
3856                 if (oklass->reflection_info && !oklass->interface_offsets)
3857                         /* 
3858                          * oklass might be a generic type parameter but they have 
3859                          * interface_offsets set.
3860                          */
3861                         return mono_reflection_call_is_assignable_to (oklass, klass);
3862
3863                 if ((klass->interface_id <= oklass->max_interface_id) &&
3864                     (oklass->interface_offsets [klass->interface_id] != -1))
3865                         return TRUE;
3866         } else if (klass->rank) {
3867                 MonoClass *eclass, *eoclass;
3868
3869                 if (oklass->rank != klass->rank)
3870                         return FALSE;
3871
3872                 /* vectors vs. one dimensional arrays */
3873                 if (oklass->byval_arg.type != klass->byval_arg.type)
3874                         return FALSE;
3875
3876                 eclass = klass->cast_class;
3877                 eoclass = oklass->cast_class;
3878
3879                 /* 
3880                  * a is b does not imply a[] is b[] when a is a valuetype, and
3881                  * b is a reference type.
3882                  */
3883
3884                 if (eoclass->valuetype) {
3885                         if ((eclass == mono_defaults.enum_class) || 
3886                                 (eclass == mono_defaults.enum_class->parent) ||
3887                                 (eclass == mono_defaults.object_class))
3888                                 return FALSE;
3889                 }
3890
3891                 return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
3892         } else if (mono_class_is_nullable (klass))
3893                 return (mono_class_is_assignable_from (klass->cast_class, oklass));
3894         else if (klass == mono_defaults.object_class)
3895                 return TRUE;
3896
3897         return mono_class_has_parent (oklass, klass);
3898 }       
3899
3900 /*
3901  * mono_class_get_cctor:
3902  *
3903  *   Returns the static constructor of @klass if it exists, NULL otherwise.
3904  */
3905 MonoMethod*
3906 mono_class_get_cctor (MonoClass *klass)
3907 {
3908         MonoCachedClassInfo cached_info;
3909
3910         if (!klass->has_cctor)
3911                 return NULL;
3912
3913         if (mono_class_get_cached_class_info (klass, &cached_info))
3914                 return mono_get_method (klass->image, cached_info.cctor_token, klass);
3915
3916         return mono_class_get_method_from_name_flags (klass, ".cctor", -1, METHOD_ATTRIBUTE_SPECIAL_NAME);
3917 }
3918
3919 /*
3920  * mono_class_get_finalizer:
3921  *
3922  *   Returns the finalizer method of @klass if it exists, NULL otherwise.
3923  */
3924 MonoMethod*
3925 mono_class_get_finalizer (MonoClass *klass)
3926 {
3927         MonoCachedClassInfo cached_info;
3928         static int finalize_slot = -1;
3929
3930         if (finalize_slot < 0) {
3931                 int i;
3932                 MonoClass* obj_class = mono_get_object_class ();
3933                 mono_class_setup_vtable (obj_class);
3934                 for (i = 0; i < obj_class->vtable_size; ++i) {
3935                         MonoMethod *cm = obj_class->vtable [i];
3936                
3937                         if (!strcmp (mono_method_get_name (cm), "Finalize")) {
3938                                 finalize_slot = i;
3939                                 break;
3940                         }
3941                 }
3942         }
3943
3944         if (!klass->has_finalize)
3945                 return NULL;
3946
3947         if (mono_class_get_cached_class_info (klass, &cached_info))
3948                 return mono_get_method (cached_info.finalize_image, cached_info.finalize_token, NULL);
3949         else {
3950                 mono_class_setup_vtable (klass);
3951                 return klass->vtable [finalize_slot];
3952         }
3953 }
3954
3955 /*
3956  * mono_class_needs_cctor_run:
3957  *
3958  *  Determines whenever the class has a static constructor and whenever it
3959  * needs to be called when executing CALLER.
3960  */
3961 gboolean
3962 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
3963 {
3964         MonoMethod *method;
3965
3966         method = mono_class_get_cctor (klass);
3967         if (method)
3968                 return (method == caller) ? FALSE : TRUE;
3969         else
3970                 return TRUE;
3971 }
3972
3973 /**
3974  * mono_class_array_element_size:
3975  * @klass: 
3976  *
3977  * Returns: the number of bytes an element of type @klass
3978  * uses when stored into an array.
3979  */
3980 gint32
3981 mono_class_array_element_size (MonoClass *klass)
3982 {
3983         MonoType *type = &klass->byval_arg;
3984         
3985 handle_enum:
3986         switch (type->type) {
3987         case MONO_TYPE_I1:
3988         case MONO_TYPE_U1:
3989         case MONO_TYPE_BOOLEAN:
3990                 return 1;
3991         case MONO_TYPE_I2:
3992         case MONO_TYPE_U2:
3993         case MONO_TYPE_CHAR:
3994                 return 2;
3995         case MONO_TYPE_I4:
3996         case MONO_TYPE_U4:
3997         case MONO_TYPE_R4:
3998                 return 4;
3999         case MONO_TYPE_I:
4000         case MONO_TYPE_U:
4001         case MONO_TYPE_PTR:
4002         case MONO_TYPE_CLASS:
4003         case MONO_TYPE_STRING:
4004         case MONO_TYPE_OBJECT:
4005         case MONO_TYPE_SZARRAY:
4006         case MONO_TYPE_ARRAY: 
4007         case MONO_TYPE_VAR:
4008         case MONO_TYPE_MVAR:   
4009                 return sizeof (gpointer);
4010         case MONO_TYPE_I8:
4011         case MONO_TYPE_U8:
4012         case MONO_TYPE_R8:
4013                 return 8;
4014         case MONO_TYPE_VALUETYPE:
4015                 if (type->data.klass->enumtype) {
4016                         type = type->data.klass->enum_basetype;
4017                         klass = klass->element_class;
4018                         goto handle_enum;
4019                 }
4020                 return mono_class_instance_size (klass) - sizeof (MonoObject);
4021         case MONO_TYPE_GENERICINST:
4022                 type = &type->data.generic_class->container_class->byval_arg;
4023                 goto handle_enum;
4024         default:
4025                 g_error ("unknown type 0x%02x in mono_class_array_element_size", type->type);
4026         }
4027         return -1;
4028 }
4029
4030 /**
4031  * mono_array_element_size:
4032  * @ac: pointer to a #MonoArrayClass
4033  *
4034  * Returns: the size of single array element.
4035  */
4036 gint32
4037 mono_array_element_size (MonoClass *ac)
4038 {
4039         return mono_class_array_element_size (ac->element_class);
4040 }
4041
4042 gpointer
4043 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class,
4044               MonoGenericContext *context)
4045 {
4046         if (image->dynamic) {
4047                 MonoClass *tmp_handle_class;
4048                 gpointer obj = mono_lookup_dynamic_token_class (image, token, &tmp_handle_class);
4049
4050                 g_assert (tmp_handle_class);
4051                 if (handle_class)
4052                         *handle_class = tmp_handle_class;
4053
4054                 if (tmp_handle_class == mono_defaults.typehandle_class)
4055                         return &((MonoClass*)obj)->byval_arg;
4056                 else
4057                         return obj;
4058         }
4059
4060         switch (token & 0xff000000) {
4061         case MONO_TOKEN_TYPE_DEF:
4062         case MONO_TOKEN_TYPE_REF:
4063         case MONO_TOKEN_TYPE_SPEC: {
4064                 MonoClass *class;
4065                 if (handle_class)
4066                         *handle_class = mono_defaults.typehandle_class;
4067                 class = mono_class_get_full (image, token, context);
4068                 if (!class)
4069                         return NULL;
4070                 mono_class_init (class);
4071                 /* We return a MonoType* as handle */
4072                 return &class->byval_arg;
4073         }
4074         case MONO_TOKEN_FIELD_DEF: {
4075                 MonoClass *class;
4076                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
4077                 if (handle_class)
4078                         *handle_class = mono_defaults.fieldhandle_class;
4079                 class = mono_class_get_full (image, MONO_TOKEN_TYPE_DEF | type, context);
4080                 if (!class)
4081                         return NULL;
4082                 mono_class_init (class);
4083                 return mono_class_get_field (class, token);
4084         }
4085         case MONO_TOKEN_METHOD_DEF: {
4086                 MonoMethod *meth;
4087                 meth = mono_get_method_full (image, token, NULL, context);
4088                 if (handle_class)
4089                         *handle_class = mono_defaults.methodhandle_class;
4090                 return meth;
4091         }
4092         case MONO_TOKEN_MEMBER_REF: {
4093                 guint32 cols [MONO_MEMBERREF_SIZE];
4094                 const char *sig;
4095                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
4096                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
4097                 mono_metadata_decode_blob_size (sig, &sig);
4098                 if (*sig == 0x6) { /* it's a field */
4099                         MonoClass *klass;
4100                         MonoClassField *field;
4101                         field = mono_field_from_token (image, token, &klass, context);
4102                         if (handle_class)
4103                                 *handle_class = mono_defaults.fieldhandle_class;
4104                         return field;
4105                 } else {
4106                         MonoMethod *meth;
4107                         meth = mono_get_method_full (image, token, NULL, context);
4108                         if (handle_class)
4109                                 *handle_class = mono_defaults.methodhandle_class;
4110                         return meth;
4111                 }
4112         }
4113         default:
4114                 g_warning ("Unknown token 0x%08x in ldtoken", token);
4115                 break;
4116         }
4117         return NULL;
4118 }
4119
4120 /**
4121  * This function might need to call runtime functions so it can't be part
4122  * of the metadata library.
4123  */
4124 static MonoLookupDynamicToken lookup_dynamic = NULL;
4125
4126 void
4127 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
4128 {
4129         lookup_dynamic = func;
4130 }
4131
4132 gpointer
4133 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
4134 {
4135         MonoClass *handle_class;
4136
4137         return lookup_dynamic (image, token, &handle_class);
4138 }
4139
4140 gpointer
4141 mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, MonoClass **handle_class)
4142 {
4143         return lookup_dynamic (image, token, handle_class);
4144 }
4145
4146 static MonoGetCachedClassInfo get_cached_class_info = NULL;
4147
4148 void
4149 mono_install_get_cached_class_info (MonoGetCachedClassInfo func)
4150 {
4151         get_cached_class_info = func;
4152 }
4153
4154 static gboolean
4155 mono_class_get_cached_class_info (MonoClass *klass, MonoCachedClassInfo *res)
4156 {
4157         if (!get_cached_class_info)
4158                 return FALSE;
4159         else
4160                 return get_cached_class_info (klass, res);
4161 }
4162
4163 MonoImage*
4164 mono_class_get_image (MonoClass *klass)
4165 {
4166         return klass->image;
4167 }
4168
4169 /**
4170  * mono_class_get_element_class:
4171  * @klass: the MonoClass to act on
4172  *
4173  * Returns: the element class of an array or an enumeration.
4174  */
4175 MonoClass*
4176 mono_class_get_element_class (MonoClass *klass)
4177 {
4178         return klass->element_class;
4179 }
4180
4181 /**
4182  * mono_class_is_valuetype:
4183  * @klass: the MonoClass to act on
4184  *
4185  * Returns: true if the MonoClass represents a ValueType.
4186  */
4187 gboolean
4188 mono_class_is_valuetype (MonoClass *klass)
4189 {
4190         return klass->valuetype;
4191 }
4192
4193 /**
4194  * mono_class_is_enum:
4195  * @klass: the MonoClass to act on
4196  *
4197  * Returns: true if the MonoClass represents an enumeration.
4198  */
4199 gboolean
4200 mono_class_is_enum (MonoClass *klass)
4201 {
4202         return klass->enumtype;
4203 }
4204
4205 /**
4206  * mono_class_enum_basetype:
4207  * @klass: the MonoClass to act on
4208  *
4209  * Returns: the underlying type representation for an enumeration.
4210  */
4211 MonoType*
4212 mono_class_enum_basetype (MonoClass *klass)
4213 {
4214         return klass->enum_basetype;
4215 }
4216
4217 /**
4218  * mono_class_get_parent
4219  * @klass: the MonoClass to act on
4220  *
4221  * Returns: the parent class for this class.
4222  */
4223 MonoClass*
4224 mono_class_get_parent (MonoClass *klass)
4225 {
4226         return klass->parent;
4227 }
4228
4229 /**
4230  * mono_class_get_nesting_type;
4231  * @klass: the MonoClass to act on
4232  *
4233  * Returns: the container type where this type is nested or NULL if this type is not a nested type.
4234  */
4235 MonoClass*
4236 mono_class_get_nesting_type (MonoClass *klass)
4237 {
4238         return klass->nested_in;
4239 }
4240
4241 /**
4242  * mono_class_get_rank:
4243  * @klass: the MonoClass to act on
4244  *
4245  * Returns: the rank for the array (the number of dimensions).
4246  */
4247 int
4248 mono_class_get_rank (MonoClass *klass)
4249 {
4250         return klass->rank;
4251 }
4252
4253 /**
4254  * mono_class_get_flags:
4255  * @klass: the MonoClass to act on
4256  *
4257  * The type flags from the TypeDef table from the metadata.
4258  * see the TYPE_ATTRIBUTE_* definitions on tabledefs.h for the
4259  * different values.
4260  *
4261  * Returns: the flags from the TypeDef table.
4262  */
4263 guint32
4264 mono_class_get_flags (MonoClass *klass)
4265 {
4266         return klass->flags;
4267 }
4268
4269 /**
4270  * mono_class_get_name
4271  * @klass: the MonoClass to act on
4272  *
4273  * Returns: the name of the class.
4274  */
4275 const char*
4276 mono_class_get_name (MonoClass *klass)
4277 {
4278         return klass->name;
4279 }
4280
4281 /**
4282  * mono_class_get_namespace:
4283  * @klass: the MonoClass to act on
4284  *
4285  * Returns: the namespace of the class.
4286  */
4287 const char*
4288 mono_class_get_namespace (MonoClass *klass)
4289 {
4290         return klass->name_space;
4291 }
4292
4293 /**
4294  * mono_class_get_type:
4295  * @klass: the MonoClass to act on
4296  *
4297  * This method returns the internal Type representation for the class.
4298  *
4299  * Returns: the MonoType from the class.
4300  */
4301 MonoType*
4302 mono_class_get_type (MonoClass *klass)
4303 {
4304         return &klass->byval_arg;
4305 }
4306
4307 /**
4308  * mono_class_get_byref_type:
4309  * @klass: the MonoClass to act on
4310  *
4311  * 
4312  */
4313 MonoType*
4314 mono_class_get_byref_type (MonoClass *klass)
4315 {
4316         return &klass->this_arg;
4317 }
4318
4319 /**
4320  * mono_class_num_fields:
4321  * @klass: the MonoClass to act on
4322  *
4323  * Returns: the number of static and instance fields in the class.
4324  */
4325 int
4326 mono_class_num_fields (MonoClass *klass)
4327 {
4328         return klass->field.count;
4329 }
4330
4331 /**
4332  * mono_class_num_methods:
4333  * @klass: the MonoClass to act on
4334  *
4335  * Returns: the number of methods in the class.
4336  */
4337 int
4338 mono_class_num_methods (MonoClass *klass)
4339 {
4340         return klass->method.count;
4341 }
4342
4343 /**
4344  * mono_class_num_properties
4345  * @klass: the MonoClass to act on
4346  *
4347  * Returns: the number of properties in the class.
4348  */
4349 int
4350 mono_class_num_properties (MonoClass *klass)
4351 {
4352         mono_class_setup_properties (klass);
4353
4354         return klass->property.count;
4355 }
4356
4357 /**
4358  * mono_class_num_events:
4359  * @klass: the MonoClass to act on
4360  *
4361  * Returns: the number of events in the class.
4362  */
4363 int
4364 mono_class_num_events (MonoClass *klass)
4365 {
4366         mono_class_setup_events (klass);
4367
4368         return klass->event.count;
4369 }
4370
4371 /**
4372  * mono_class_get_fields:
4373  * @klass: the MonoClass to act on
4374  *
4375  * This routine is an iterator routine for retrieving the fields in a class.
4376  *
4377  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4378  * iterate over all of the elements.  When no more values are
4379  * available, the return value is NULL.
4380  *
4381  * Returns: a @MonoClassField* on each iteration, or NULL when no more fields are available.
4382  */
4383 MonoClassField*
4384 mono_class_get_fields (MonoClass* klass, gpointer *iter)
4385 {
4386         MonoClassField* field;
4387         if (!iter)
4388                 return NULL;
4389         mono_class_setup_fields_locking (klass);
4390         if (!*iter) {
4391                 /* start from the first */
4392                 if (klass->field.count) {
4393                         return *iter = &klass->fields [0];
4394                 } else {
4395                         /* no fields */
4396                         return NULL;
4397                 }
4398         }
4399         field = *iter;
4400         field++;
4401         if (field < &klass->fields [klass->field.count]) {
4402                 return *iter = field;
4403         }
4404         return NULL;
4405 }
4406
4407 /**
4408  * mono_class_get_methods
4409  * @klass: the MonoClass to act on
4410  *
4411  * This routine is an iterator routine for retrieving the fields in a class.
4412  *
4413  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4414  * iterate over all of the elements.  When no more values are
4415  * available, the return value is NULL.
4416  *
4417  * Returns: a MonoMethod on each iteration or NULL when no more methods are available.
4418  */
4419 MonoMethod*
4420 mono_class_get_methods (MonoClass* klass, gpointer *iter)
4421 {
4422         MonoMethod** method;
4423         if (!iter)
4424                 return NULL;
4425         if (!klass->inited)
4426                 mono_class_init (klass);
4427         if (!*iter) {
4428                 mono_class_setup_methods (klass);
4429                 /* start from the first */
4430                 if (klass->method.count) {
4431                         *iter = &klass->methods [0];
4432                         return klass->methods [0];
4433                 } else {
4434                         /* no method */
4435                         return NULL;
4436                 }
4437         }
4438         method = *iter;
4439         method++;
4440         if (method < &klass->methods [klass->method.count]) {
4441                 *iter = method;
4442                 return *method;
4443         }
4444         return NULL;
4445 }
4446
4447 /**
4448  * mono_class_get_properties:
4449  * @klass: the MonoClass to act on
4450  *
4451  * This routine is an iterator routine for retrieving the properties in a class.
4452  *
4453  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4454  * iterate over all of the elements.  When no more values are
4455  * available, the return value is NULL.
4456  *
4457  * Returns: a @MonoProperty* on each invocation, or NULL when no more are available.
4458  */
4459 MonoProperty*
4460 mono_class_get_properties (MonoClass* klass, gpointer *iter)
4461 {
4462         MonoProperty* property;
4463         if (!iter)
4464                 return NULL;
4465         if (!klass->inited)
4466                 mono_class_init (klass);
4467         if (!*iter) {
4468                 mono_class_setup_properties (klass);
4469                 /* start from the first */
4470                 if (klass->property.count) {
4471                         return *iter = &klass->properties [0];
4472                 } else {
4473                         /* no fields */
4474                         return NULL;
4475                 }
4476         }
4477         property = *iter;
4478         property++;
4479         if (property < &klass->properties [klass->property.count]) {
4480                 return *iter = property;
4481         }
4482         return NULL;
4483 }
4484
4485 /**
4486  * mono_class_get_events:
4487  * @klass: the MonoClass to act on
4488  *
4489  * This routine is an iterator routine for retrieving the properties in a class.
4490  *
4491  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4492  * iterate over all of the elements.  When no more values are
4493  * available, the return value is NULL.
4494  *
4495  * Returns: a @MonoEvent* on each invocation, or NULL when no more are available.
4496  */
4497 MonoEvent*
4498 mono_class_get_events (MonoClass* klass, gpointer *iter)
4499 {
4500         MonoEvent* event;
4501         if (!iter)
4502                 return NULL;
4503         if (!klass->inited)
4504                 mono_class_init (klass);
4505         if (!*iter) {
4506                 mono_class_setup_events (klass);
4507                 /* start from the first */
4508                 if (klass->event.count) {
4509                         return *iter = &klass->events [0];
4510                 } else {
4511                         /* no fields */
4512                         return NULL;
4513                 }
4514         }
4515         event = *iter;
4516         event++;
4517         if (event < &klass->events [klass->event.count]) {
4518                 return *iter = event;
4519         }
4520         return NULL;
4521 }
4522
4523 /**
4524  * mono_class_get_interfaces
4525  * @klass: the MonoClass to act on
4526  *
4527  * This routine is an iterator routine for retrieving the interfaces implemented by this class.
4528  *
4529  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4530  * iterate over all of the elements.  When no more values are
4531  * available, the return value is NULL.
4532  *
4533  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
4534  */
4535 MonoClass*
4536 mono_class_get_interfaces (MonoClass* klass, gpointer *iter)
4537 {
4538         MonoClass** iface;
4539         if (!iter)
4540                 return NULL;
4541         if (!klass->inited)
4542                 mono_class_init (klass);
4543         if (!*iter) {
4544                 /* start from the first */
4545                 if (klass->interface_count) {
4546                         *iter = &klass->interfaces [0];
4547                         return klass->interfaces [0];
4548                 } else {
4549                         /* no interface */
4550                         return NULL;
4551                 }
4552         }
4553         iface = *iter;
4554         iface++;
4555         if (iface < &klass->interfaces [klass->interface_count]) {
4556                 *iter = iface;
4557                 return *iface;
4558         }
4559         return NULL;
4560 }
4561
4562 /**
4563  * mono_class_get_nested_types
4564  * @klass: the MonoClass to act on
4565  *
4566  * This routine is an iterator routine for retrieving the nested types of a class.
4567  *
4568  * You must pass a gpointer that points to zero and is treated as an opaque handle to
4569  * iterate over all of the elements.  When no more values are
4570  * available, the return value is NULL.
4571  *
4572  * Returns: a @Monoclass* on each invocation, or NULL when no more are available.
4573  */
4574 MonoClass*
4575 mono_class_get_nested_types (MonoClass* klass, gpointer *iter)
4576 {
4577         GList *item;
4578         if (!iter)
4579                 return NULL;
4580         if (!klass->inited)
4581                 mono_class_init (klass);
4582         if (!*iter) {
4583                 /* start from the first */
4584                 if (klass->nested_classes) {
4585                         *iter = klass->nested_classes;
4586                         return klass->nested_classes->data;
4587                 } else {
4588                         /* no nested types */
4589                         return NULL;
4590                 }
4591         }
4592         item = *iter;
4593         item = item->next;
4594         if (item) {
4595                 *iter = item;
4596                 return item->data;
4597         }
4598         return NULL;
4599 }
4600
4601 /**
4602  * mono_field_get_name:
4603  * @field: the MonoClassField to act on
4604  *
4605  * Returns: the name of the field.
4606  */
4607 const char*
4608 mono_field_get_name (MonoClassField *field)
4609 {
4610         return field->name;
4611 }
4612
4613 /**
4614  * mono_field_get_type:
4615  * @field: the MonoClassField to act on
4616  *
4617  * Returns: MonoType of the field.
4618  */
4619 MonoType*
4620 mono_field_get_type (MonoClassField *field)
4621 {
4622         return field->type;
4623 }
4624
4625 /**
4626  * mono_field_get_type:
4627  * @field: the MonoClassField to act on
4628  *
4629  * Returns: MonoClass where the field was defined.
4630  */
4631 MonoClass*
4632 mono_field_get_parent (MonoClassField *field)
4633 {
4634         return field->parent;
4635 }
4636
4637 /**
4638  * mono_field_get_flags;
4639  * @field: the MonoClassField to act on
4640  *
4641  * The metadata flags for a field are encoded using the
4642  * FIELD_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
4643  *
4644  * Returns: the flags for the field.
4645  */
4646 guint32
4647 mono_field_get_flags (MonoClassField *field)
4648 {
4649         return field->type->attrs;
4650 }
4651
4652 /**
4653  * mono_property_get_name: 
4654  * @prop: the MonoProperty to act on
4655  *
4656  * Returns: the name of the property
4657  */
4658 const char*
4659 mono_property_get_name (MonoProperty *prop)
4660 {
4661         return prop->name;
4662 }
4663
4664 /**
4665  * mono_property_get_set_method
4666  * @prop: the MonoProperty to act on.
4667  *
4668  * Returns: the setter method of the property (A MonoMethod)
4669  */
4670 MonoMethod*
4671 mono_property_get_set_method (MonoProperty *prop)
4672 {
4673         return prop->set;
4674 }
4675
4676 /**
4677  * mono_property_get_get_method
4678  * @prop: the MonoProperty to act on.
4679  *
4680  * Returns: the setter method of the property (A MonoMethod)
4681  */
4682 MonoMethod*
4683 mono_property_get_get_method (MonoProperty *prop)
4684 {
4685         return prop->get;
4686 }
4687
4688 /**
4689  * mono_property_get_parent:
4690  * @prop: the MonoProperty to act on.
4691  *
4692  * Returns: the MonoClass where the property was defined.
4693  */
4694 MonoClass*
4695 mono_property_get_parent (MonoProperty *prop)
4696 {
4697         return prop->parent;
4698 }
4699
4700 /**
4701  * mono_property_get_flags:
4702  * @prop: the MonoProperty to act on.
4703  *
4704  * The metadata flags for a property are encoded using the
4705  * PROPERTY_ATTRIBUTE_* constants.  See the tabledefs.h file for details.
4706  *
4707  * Returns: the flags for the property.
4708  */
4709 guint32
4710 mono_property_get_flags (MonoProperty *prop)
4711 {
4712         return prop->attrs;
4713 }
4714
4715 /**
4716  * mono_event_get_name:
4717  * @event: the MonoEvent to act on
4718  *
4719  * Returns: the name of the event.
4720  */
4721 const char*
4722 mono_event_get_name (MonoEvent *event)
4723 {
4724         return event->name;
4725 }
4726
4727 /**
4728  * mono_event_get_add_method:
4729  * @event: The MonoEvent to act on.
4730  *
4731  * Returns: the @add' method for the event (a MonoMethod).
4732  */
4733 MonoMethod*
4734 mono_event_get_add_method (MonoEvent *event)
4735 {
4736         return event->add;
4737 }
4738
4739 /**
4740  * mono_event_get_remove_method:
4741  * @event: The MonoEvent to act on.
4742  *
4743  * Returns: the @remove method for the event (a MonoMethod).
4744  */
4745 MonoMethod*
4746 mono_event_get_remove_method (MonoEvent *event)
4747 {
4748         return event->remove;
4749 }
4750
4751 /**
4752  * mono_event_get_raise_method:
4753  * @event: The MonoEvent to act on.
4754  *
4755  * Returns: the @raise method for the event (a MonoMethod).
4756  */
4757 MonoMethod*
4758 mono_event_get_raise_method (MonoEvent *event)
4759 {
4760         return event->raise;
4761 }
4762
4763 /**
4764  * mono_event_get_parent:
4765  * @event: the MonoEvent to act on.
4766  *
4767  * Returns: the MonoClass where the event is defined.
4768  */
4769 MonoClass*
4770 mono_event_get_parent (MonoEvent *event)
4771 {
4772         return event->parent;
4773 }
4774
4775 /**
4776  * mono_event_get_flags
4777  * @event: the MonoEvent to act on.
4778  *
4779  * The metadata flags for an event are encoded using the
4780  * EVENT_* constants.  See the tabledefs.h file for details.
4781  *
4782  * Returns: the flags for the event.
4783  */
4784 guint32
4785 mono_event_get_flags (MonoEvent *event)
4786 {
4787         return event->attrs;
4788 }
4789
4790 /**
4791  * mono_class_get_method_from_name:
4792  * @klass: where to look for the method
4793  * @name_space: name of the method
4794  * @param_count: number of parameters. -1 for any number.
4795  *
4796  * Obtains a MonoMethod with a given name and number of parameters.
4797  * It only works if there are no multiple signatures for any given method name.
4798  */
4799 MonoMethod *
4800 mono_class_get_method_from_name (MonoClass *klass, const char *name, int param_count)
4801 {
4802         return mono_class_get_method_from_name_flags (klass, name, param_count, 0);
4803 }
4804
4805 /**
4806  * mono_class_get_method_from_name_flags:
4807  * @klass: where to look for the method
4808  * @name_space: name of the method
4809  * @param_count: number of parameters. -1 for any number.
4810  * @flags: flags which must be set in the method
4811  *
4812  * Obtains a MonoMethod with a given name and number of parameters.
4813  * It only works if there are no multiple signatures for any given method name.
4814  */
4815 MonoMethod *
4816 mono_class_get_method_from_name_flags (MonoClass *klass, const char *name, int param_count, int flags)
4817 {
4818         MonoMethod *res = NULL;
4819         int i;
4820
4821         mono_class_init (klass);
4822
4823         if (klass->methods) {
4824                 mono_class_setup_methods (klass);
4825                 for (i = 0; i < klass->method.count; ++i) {
4826                         MonoMethod *method = klass->methods [i];
4827
4828                         if (method->name[0] == name [0] && 
4829                                 !strcmp (name, method->name) &&
4830                                 (param_count == -1 || mono_method_signature (method)->param_count == param_count) &&
4831                                 ((method->flags & flags) == flags)) {
4832                                 res = method;
4833                                 break;
4834                         }
4835                 }
4836         }
4837         else {
4838                 /* Search directly in the metadata to avoid calling setup_methods () */
4839                 for (i = 0; i < klass->method.count; ++i) {
4840                         guint32 cols [MONO_METHOD_SIZE];
4841                         MonoMethod *method;
4842
4843                         mono_metadata_decode_row (&klass->image->tables [MONO_TABLE_METHOD], klass->method.first + i, cols, MONO_METHOD_SIZE);
4844
4845                         if (!strcmp (mono_metadata_string_heap (klass->image, cols [MONO_METHOD_NAME]), name)) {
4846                                 method = mono_get_method (klass->image, MONO_TOKEN_METHOD_DEF | (klass->method.first + i + 1), klass);
4847                                 if ((param_count == -1) || mono_method_signature (method)->param_count == param_count) {
4848                                         res = method;
4849                                         break;
4850                                 }
4851                         }
4852                 }
4853         }
4854
4855         return res;
4856 }
4857
4858 /**
4859  * mono_class_set_failure:
4860  * @klass: class in which the failure was detected
4861  * @ex_type: the kind of exception/error to be thrown (later)
4862  * @ex_data: exception data (specific to each type of exception/error)
4863  *
4864  * Keep a detected failure informations in the class for later processing.
4865  * Note that only the first failure is kept.
4866  */
4867 gboolean
4868 mono_class_set_failure (MonoClass *klass, guint32 ex_type, void *ex_data)
4869 {
4870         if (klass->exception_type)
4871                 return FALSE;
4872         klass->exception_type = ex_type;
4873         klass->exception_data = ex_data;
4874         return TRUE;
4875 }
4876
4877 /**
4878  * mono_class_get_exception_for_failure:
4879  * @klass: class in which the failure was detected
4880  *
4881  * Return a constructed MonoException than the caller can then throw
4882  * using mono_raise_exception - or NULL if no failure is present (or
4883  * doesn't result in an exception).
4884  */
4885 MonoException*
4886 mono_class_get_exception_for_failure (MonoClass *klass)
4887 {
4888         switch (klass->exception_type) {
4889         case MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND: {
4890                 MonoDomain *domain = mono_domain_get ();
4891                 MonoSecurityManager* secman = mono_security_manager_get_methods ();
4892                 MonoMethod *method = klass->exception_data;
4893                 guint32 error = (method) ? MONO_METADATA_INHERITANCEDEMAND_METHOD : MONO_METADATA_INHERITANCEDEMAND_CLASS;
4894                 MonoObject *exc = NULL;
4895                 gpointer args [4];
4896
4897                 args [0] = &error;
4898                 args [1] = mono_assembly_get_object (domain, mono_image_get_assembly (klass->image));
4899                 args [2] = mono_type_get_object (domain, &klass->byval_arg);
4900                 args [3] = (method) ? mono_method_get_object (domain, method, NULL) : NULL;
4901
4902                 mono_runtime_invoke (secman->inheritsecurityexception, NULL, args, &exc);
4903                 return (MonoException*) exc;
4904         }
4905         case MONO_EXCEPTION_TYPE_LOAD:
4906                 return mono_exception_from_name (mono_defaults.corlib, "System", "TypeLoadException");
4907         /* TODO - handle other class related failures */
4908         default:
4909                 return NULL;
4910         }
4911 }