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