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