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