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