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