2004-03-09 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/tabledefs.h>
27 #include <mono/metadata/tokentype.h>
28 #include <mono/metadata/class.h>
29 #include <mono/metadata/object.h>
30 #include <mono/metadata/appdomain.h>
31 #include <mono/metadata/mono-endian.h>
32 #include <mono/metadata/debug-helpers.h>
33 #include <mono/metadata/reflection.h>
34 #include <mono/os/gc_wrapper.h>
35
36 MonoStats mono_stats;
37
38 gboolean mono_print_vtable = FALSE;
39
40 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
41
42 void (*mono_debugger_class_init_func) (MonoClass *klass) = NULL;
43
44 MonoClass *
45 mono_class_from_typeref (MonoImage *image, guint32 type_token)
46 {
47         guint32 cols [MONO_TYPEREF_SIZE];
48         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEREF];
49         guint32 idx;
50         const char *name, *nspace;
51         MonoClass *res;
52         MonoAssembly **references;
53
54         mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
55
56         name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
57         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
58         
59         idx = cols [MONO_TYPEREF_SCOPE] >> RESOLTION_SCOPE_BITS;
60         switch (cols [MONO_TYPEREF_SCOPE] & RESOLTION_SCOPE_MASK) {
61         case RESOLTION_SCOPE_MODULE:
62                 if (!idx)
63                         g_error ("null ResolutionScope not yet handled");
64                 /* a typedef in disguise */
65                 return mono_class_from_name (image, nspace, name);
66         case RESOLTION_SCOPE_MODULEREF:
67                 return mono_class_from_name (image->modules [idx - 1], nspace, name);
68         case RESOLTION_SCOPE_TYPEREF: {
69                 MonoClass *enclosing = mono_class_from_typeref (image, MONO_TOKEN_TYPE_REF | idx);
70                 GList *tmp;
71                 mono_class_init (enclosing);
72                 for (tmp = enclosing->nested_classes; tmp; tmp = tmp->next) {
73                         res = tmp->data;
74                         if (strcmp (res->name, name) == 0)
75                                 return res;
76                 }
77                 g_warning ("TypeRef ResolutionScope not yet handled (%d)", idx);
78                 return NULL;
79         }
80         case RESOLTION_SCOPE_ASSEMBLYREF:
81                 break;
82         }
83
84         references = image->references;
85         if (!references ||  !references [idx-1]) {
86                 /* 
87                  * detected a reference to mscorlib, we simply return a reference to a dummy 
88                  * until we have a better solution.
89                  */
90                 fprintf(stderr, "Sending dummy where %s.%s expected\n", mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]), mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME])); 
91                 
92                 res = mono_class_from_name (image, "System", "MonoDummy");
93                 /* prevent method loading */
94                 res->dummy = 1;
95                 /* some storage if the type is used  - very ugly hack */
96                 res->instance_size = 2*sizeof (gpointer);
97                 return res;
98         }       
99
100         /* load referenced assembly */
101         image = references [idx-1]->image;
102
103         return mono_class_from_name (image, nspace, name);
104 }
105
106 static MonoType*
107 dup_type (MonoType* t)
108 {
109         MonoType *r = g_new0 (MonoType, 1);
110         *r = *t;
111         return r;
112 }
113
114 static void
115 mono_type_get_name_recurse (MonoType *type, GString *str)
116 {
117         MonoClass *klass;
118         
119         switch (type->type) {
120         case MONO_TYPE_ARRAY: {
121                 int i, rank = type->data.array->rank;
122
123                 mono_type_get_name_recurse (&type->data.array->eklass->byval_arg, str);
124                 g_string_append_c (str, '[');
125                 for (i = 1; i < rank; i++)
126                         g_string_append_c (str, ',');
127                 g_string_append_c (str, ']');
128                 break;
129         }
130         case MONO_TYPE_SZARRAY:
131                 mono_type_get_name_recurse (&type->data.klass->byval_arg, str);
132                 g_string_append (str, "[]");
133                 break;
134         case MONO_TYPE_PTR:
135                 mono_type_get_name_recurse (type->data.type, str);
136                 g_string_append_c (str, '*');
137                 break;
138         default:
139                 klass = mono_class_from_mono_type (type);
140                 if (klass->nested_in) {
141                         mono_type_get_name_recurse (&klass->nested_in->byval_arg, str);
142                         g_string_append_c (str, '+');
143                 }
144                 if (*klass->name_space) {
145                         g_string_append (str, klass->name_space);
146                         g_string_append_c (str, '.');
147                 }
148                 g_string_append (str, klass->name);
149                 break;
150         }
151 }
152
153 /*
154  * mono_type_get_name:
155  * @type: a type
156  *
157  * Returns the string representation for type as required by System.Reflection.
158  * The inverse of mono_reflection_parse_type ().
159  */
160 char*
161 mono_type_get_name (MonoType *type)
162 {
163         GString* result = g_string_new ("");
164         mono_type_get_name_recurse (type, result);
165
166         if (type->byref)
167                 g_string_append_c (result, '&');
168
169         return g_string_free (result, FALSE);
170 }
171
172 gboolean
173 mono_class_is_open_constructed_type (MonoType *t)
174 {
175         switch (t->type) {
176         case MONO_TYPE_VAR:
177         case MONO_TYPE_MVAR:
178                 return TRUE;
179         case MONO_TYPE_SZARRAY:
180                 return mono_class_is_open_constructed_type (&t->data.klass->byval_arg);
181         case MONO_TYPE_ARRAY:
182                 return mono_class_is_open_constructed_type (&t->data.array->eklass->byval_arg);
183         case MONO_TYPE_PTR:
184                 return mono_class_is_open_constructed_type (t->data.type);
185         case MONO_TYPE_GENERICINST: {
186                 MonoGenericInst *ginst = t->data.generic_inst;
187                 int i;
188
189                 if (mono_class_is_open_constructed_type (ginst->generic_type))
190                         return TRUE;
191                 for (i = 0; i < ginst->type_argc; i++)
192                         if (mono_class_is_open_constructed_type (ginst->type_argv [i]))
193                                 return TRUE;
194                 return FALSE;
195         }
196         default:
197                 return FALSE;
198         }
199 }
200
201 MonoType*
202 mono_class_inflate_generic_type (MonoType *type, MonoGenericInst *ginst,
203                                  MonoGenericMethod *gmethod)
204 {
205         switch (type->type) {
206         case MONO_TYPE_MVAR:
207                 if (gmethod && gmethod->mtype_argv)
208                         return dup_type (gmethod->mtype_argv [type->data.generic_param->num]);
209                 else
210                         return type;
211         case MONO_TYPE_VAR:
212                 if (ginst)
213                         return dup_type (ginst->type_argv [type->data.generic_param->num]);
214                 else
215                         return type;
216         case MONO_TYPE_SZARRAY: {
217                 MonoClass *eclass = type->data.klass;
218                 MonoClass *nclass;
219                 MonoType *nt;
220                 if ((eclass->byval_arg.type == MONO_TYPE_MVAR) && gmethod) {
221                         nclass = mono_class_from_mono_type (gmethod->mtype_argv [eclass->byval_arg.data.generic_param->num]);
222                 } else if ((eclass->byval_arg.type == MONO_TYPE_VAR) && ginst) {
223                         nclass = mono_class_from_mono_type (ginst->type_argv [eclass->byval_arg.data.generic_param->num]);
224                 } else {
225                         return type;
226                 }
227                 nt = dup_type (type);
228                 nt->data.klass = nclass;
229                 return nt;
230         }
231         case MONO_TYPE_GENERICINST: {
232                 MonoGenericInst *oginst = type->data.generic_inst;
233                 MonoGenericInst *nginst;
234                 MonoType *nt;
235                 int i;
236
237                 nginst = g_new0 (MonoGenericInst, 1);
238                 *nginst = *oginst;
239
240                 nginst->is_open = FALSE;
241
242                 nginst->type_argv = g_new0 (MonoType *, oginst->type_argc);
243
244                 for (i = 0; i < oginst->type_argc; i++) {
245                         MonoType *t = oginst->type_argv [i];
246                         nginst->type_argv [i] = mono_class_inflate_generic_type (t, ginst, gmethod);
247
248                         if (!nginst->is_open)
249                                 nginst->is_open = mono_class_is_open_constructed_type (nginst->type_argv [i]);
250                 };
251
252                 nginst->klass = NULL;
253
254                 mono_loader_lock ();
255                 nt = g_hash_table_lookup (oginst->klass->image->generic_inst_cache, nginst);
256
257                 if (nt) {
258                         g_free (nginst->type_argv);
259                         g_free (nginst);
260                         mono_loader_unlock ();
261                         return nt;
262                 }
263
264                 mono_class_create_generic (nginst);
265
266                 nt = dup_type (type);
267                 nt->data.generic_inst = nginst;
268                 g_hash_table_insert (oginst->klass->image->generic_inst_cache, nginst, nt);
269                 mono_loader_unlock ();
270                 return nt;
271         }
272         default:
273                 return type;
274         }
275         return type;
276 }
277
278 static MonoMethodSignature*
279 inflate_generic_signature (MonoImage *image, MonoMethodSignature *sig,
280                            MonoGenericMethod *gmethod)
281 {
282         MonoMethodSignature *res;
283         int i;
284         res = mono_metadata_signature_alloc (image, sig->param_count);
285         res->ret = mono_class_inflate_generic_type (sig->ret, gmethod->generic_inst, gmethod);
286         for (i = 0; i < sig->param_count; ++i)
287                 res->params [i] = mono_class_inflate_generic_type (sig->params [i],
288                                                                    gmethod->generic_inst,
289                                                                    gmethod);
290         res->hasthis = sig->hasthis;
291         res->explicit_this = sig->explicit_this;
292         res->call_convention = sig->call_convention;
293         res->generic_param_count = sig->generic_param_count;
294         res->gen_method = gmethod;
295         return res;
296 }
297
298 static MonoMethodHeader*
299 inflate_generic_header (MonoMethodHeader *header, MonoGenericMethod *gmethod)
300 {
301         MonoMethodHeader *res;
302         int i;
303         res = g_malloc0 (sizeof (MonoMethodHeader) + sizeof (gpointer) * header->num_locals);
304         res->code = header->code;
305         res->code_size = header->code_size;
306         res->max_stack = header->max_stack;
307         res->num_clauses = header->num_clauses;
308         res->init_locals = header->init_locals;
309         res->num_locals = header->num_locals;
310         res->clauses = header->clauses;
311         res->gen_params = header->gen_params;
312         for (i = 0; i < header->num_locals; ++i)
313                 res->locals [i] = mono_class_inflate_generic_type (header->locals [i],
314                                                                    gmethod->generic_inst,
315                                                                    gmethod);
316         return res;
317 }
318
319 MonoMethod*
320 mono_class_inflate_generic_method (MonoMethod *method, MonoGenericMethod *gmethod,
321                                    MonoClass *klass)
322 {
323         MonoMethod *result;
324         if ((method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) || (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
325                 MonoMethodPInvoke *nmethod = g_new0 (MonoMethodPInvoke, 1);
326                 *nmethod = *(MonoMethodPInvoke*)method;
327                 result = (MonoMethod*)nmethod;
328         } else {
329                 MonoMethodNormal *nmethod = g_new0 (MonoMethodNormal, 1);
330                 *nmethod = *(MonoMethodNormal*)method;
331                 result = (MonoMethod*)nmethod;
332                 if (nmethod->header)
333                         nmethod->header = inflate_generic_header (nmethod->header, gmethod);
334         }
335         if (klass)
336                 result->klass = klass;
337         else {
338                 MonoType *declaring = mono_class_inflate_generic_type (
339                         &method->klass->byval_arg, gmethod->generic_inst, gmethod);
340                 result->klass = mono_class_from_mono_type (declaring);
341         }
342
343         result->signature = inflate_generic_signature (
344                 method->klass->image, result->signature, gmethod);
345         return result;
346 }
347
348 /** 
349  * class_compute_field_layout:
350  * @m: pointer to the metadata.
351  * @class: The class to initialize
352  *
353  * Initializes the class->fields.
354  *
355  * Currently we only support AUTO_LAYOUT, and do not even try to do
356  * a good job at it.  This is temporary to get the code for Paolo.
357  */
358 static void
359 class_compute_field_layout (MonoClass *class)
360 {
361         MonoImage *m = class->image; 
362         const int top = class->field.count;
363         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
364         MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
365         int i, blittable = TRUE, real_size = 0;
366         guint32 rva;
367         guint32 packing_size = 0;
368         gboolean explicit_size;
369         MonoClassField *field;
370
371         if (class->size_inited)
372                 return;
373
374         if (class->parent) {
375                 if (!class->parent->size_inited)
376                         class_compute_field_layout (class->parent);
377                 class->instance_size += class->parent->instance_size;
378                 class->min_align = class->parent->min_align;
379                 blittable = class->blittable;
380         } else {
381                 class->instance_size = sizeof (MonoObject);
382                 class->min_align = 1;
383         }
384
385         /* Get the real size */
386         explicit_size = mono_metadata_packing_from_typedef (class->image, class->type_token, &packing_size, &real_size);
387
388         if (explicit_size) {
389                 g_assert ((packing_size & 0xfffffff0) == 0);
390                 class->packing_size = packing_size;
391                 real_size += class->instance_size;
392         }
393
394         if (!top) {
395                 if (explicit_size && real_size) {
396                         class->instance_size = MAX (real_size, class->instance_size);
397                 }
398                 class->size_inited = 1;
399                 return;
400         }
401
402         class->fields = g_new0 (MonoClassField, top);
403
404         /*
405          * Fetch all the field information.
406          */
407         for (i = 0; i < top; i++){
408                 const char *sig;
409                 guint32 cols [MONO_FIELD_SIZE];
410                 int idx = class->field.first + i;
411
412                 field = &class->fields [i];
413                 mono_metadata_decode_row (t, idx, cols, MONO_FIELD_SIZE);
414                 /* The name is needed for fieldrefs */
415                 field->name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
416                 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
417                 mono_metadata_decode_value (sig, &sig);
418                 /* FIELD signature == 0x06 */
419                 g_assert (*sig == 0x06);
420                 field->type = mono_metadata_parse_field_type (
421                         m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
422                 if (mono_field_is_deleted (field))
423                         continue;
424                 if (class->generic_inst) {
425                         field->type = mono_class_inflate_generic_type (field->type, class->generic_inst, NULL);
426                         field->type->attrs = cols [MONO_FIELD_FLAGS];
427                 }
428
429                 field->parent = class;
430
431                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC)) {
432                         if (field->type->byref) {
433                                 blittable = FALSE;
434                         } else {
435                                 MonoClass *field_class = mono_class_from_mono_type (field->type);
436                                 if (!field_class || !field_class->blittable)
437                                         blittable = FALSE;
438                         }
439                 }
440                 if (layout == TYPE_ATTRIBUTE_EXPLICIT_LAYOUT) {
441                         mono_metadata_field_info (m, idx, &field->offset, NULL, NULL);
442                         if (field->offset == (guint32)-1)
443                                 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, field->name);
444                 }
445
446                 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
447                         mono_metadata_field_info (m, idx, NULL, &rva, NULL);
448                         if (!rva)
449                                 g_warning ("field %s in %s should have RVA data, but hasn't", field->name, class->name);
450                         field->data = mono_cli_rva_map (class->image->image_info, rva);
451                 }
452
453                 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
454                         class->enum_basetype = field->type;
455                         class->cast_class = class->element_class = mono_class_from_mono_type (class->enum_basetype);
456                         blittable = class->element_class->blittable;
457                 }
458
459                 /* The def_value of fields is compute lazily during vtable creation */
460         }
461
462         if (class == mono_defaults.string_class)
463                 blittable = FALSE;
464
465         class->blittable = blittable;
466
467         if (class->enumtype && !class->enum_basetype) {
468                 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
469                         G_BREAKPOINT ();
470         }
471         if (explicit_size && real_size) {
472                 class->instance_size = MAX (real_size, class->instance_size);
473         }
474
475         if (class->gen_params)
476                 return;
477
478         mono_class_layout_fields (class);
479 }
480
481 void
482 mono_class_layout_fields (MonoClass *class)
483 {
484         int i;
485         const int top = class->field.count;
486         guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
487         guint32 pass, passes, real_size;
488         gboolean gc_aware_layout = FALSE;
489         MonoClassField *field;
490
491         /*
492          * Enable GC aware auto layout: in this mode, reference
493          * fields are grouped together inside objects, increasing collector 
494          * performance.
495          * Requires that all classes whose layout is known to native code be annotated
496          * with [StructLayout (LayoutKind.Sequential)]
497          */
498          /* corlib is missing [StructLayout] directives in many places */
499         if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
500                 if (class->image != mono_defaults.corlib)
501                         gc_aware_layout = TRUE;
502         }
503
504         /*
505          * Compute field layout and total size (not considering static fields)
506          */
507
508         switch (layout) {
509         case TYPE_ATTRIBUTE_AUTO_LAYOUT:
510         case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
511
512                 if (gc_aware_layout)
513                         passes = 2;
514                 else
515                         passes = 1;
516
517                 if (layout != TYPE_ATTRIBUTE_AUTO_LAYOUT)
518                         passes = 1;
519
520                 if (class->parent)
521                         real_size = class->parent->instance_size;
522                 else
523                         real_size = sizeof (MonoObject);
524
525                 for (pass = 0; pass < passes; ++pass) {
526                         for (i = 0; i < top; i++){
527                                 int size, align;
528                                 field = &class->fields [i];
529
530                                 if (mono_field_is_deleted (field))
531                                         continue;
532                                 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
533                                         continue;
534
535                                 if (gc_aware_layout) {
536                                         /* 
537                                          * We process fields with reference type in the first pass,
538                                          * and fields with non-reference type in the second pass.
539                                          * We use IS_POINTER instead of IS_REFERENCE because in
540                                          * some internal structures, we store GC_MALLOCed memory
541                                          * in IntPtr fields...
542                                          */
543                                         if (MONO_TYPE_IS_POINTER (field->type)) {
544                                                 if (pass == 1)
545                                                         continue;
546                                         } else {
547                                                 if (pass == 0)
548                                                         continue;
549                                         }
550                                 }
551
552                                 if ((top == 1) && (class->instance_size == sizeof (MonoObject)) &&
553                                         (strcmp (field->name, "$PRIVATE$") == 0)) {
554                                         /* This field is a hack inserted by MCS to empty structures */
555                                         continue;
556                                 }
557
558                                 size = mono_type_size (field->type, &align);
559                         
560                                 /* FIXME (LAMESPEC): should we also change the min alignment according to pack? */
561                                 align = class->packing_size ? MIN (class->packing_size, align): align;
562                                 class->min_align = MAX (align, class->min_align);
563                                 field->offset = real_size;
564                                 field->offset += align - 1;
565                                 field->offset &= ~(align - 1);
566                                 real_size = field->offset + size;
567                         }
568
569                         class->instance_size = MAX (real_size, class->instance_size);
570        
571                         if (class->instance_size & (class->min_align - 1)) {
572                                 class->instance_size += class->min_align - 1;
573                                 class->instance_size &= ~(class->min_align - 1);
574                         }
575                 }
576                 break;
577         case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
578                 real_size = 0;
579                 for (i = 0; i < top; i++) {
580                         int size, align;
581                         field = &class->fields [i];
582
583                         /*
584                          * There must be info about all the fields in a type if it
585                          * uses explicit layout.
586                          */
587
588                         if (mono_field_is_deleted (field))
589                                 continue;
590                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
591                                 continue;
592
593                         size = mono_type_size (field->type, &align);
594                         
595                         /*
596                          * When we get here, field->offset is already set by the
597                          * loader (for either runtime fields or fields loaded from metadata).
598                          * The offset is from the start of the object: this works for both
599                          * classes and valuetypes.
600                          */
601                         field->offset += sizeof (MonoObject);
602
603                         /*
604                          * Calc max size.
605                          */
606                         real_size = MAX (real_size, size + field->offset);
607                 }
608                 class->instance_size = MAX (real_size, class->instance_size);
609                 break;
610         }
611
612         class->size_inited = 1;
613
614         /*
615          * Compute static field layout and size
616          */
617         for (i = 0; i < top; i++){
618                 int size, align;
619                 field = &class->fields [i];
620                         
621                 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
622                         continue;
623                 if (mono_field_is_deleted (field))
624                         continue;
625                         
626                 size = mono_type_size (field->type, &align);
627                 field->offset = class->class_size;
628                 field->offset += align - 1;
629                 field->offset &= ~(align - 1);
630                 class->class_size = field->offset + size;
631         }
632 }
633
634 static void
635 init_properties (MonoClass *class)
636 {
637         guint startm, endm, i, j;
638         guint32 cols [MONO_PROPERTY_SIZE];
639         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
640         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
641
642         class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
643         class->property.count = class->property.last - class->property.first;
644
645         class->properties = g_new0 (MonoProperty, class->property.count);
646         for (i = class->property.first; i < class->property.last; ++i) {
647                 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
648                 class->properties [i - class->property.first].parent = class;
649                 class->properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
650                 class->properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
651
652                 startm = mono_metadata_methods_from_property (class->image, i, &endm);
653                 for (j = startm; j < endm; ++j) {
654                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
655                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
656                         case METHOD_SEMANTIC_SETTER:
657                                 class->properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
658                                 break;
659                         case METHOD_SEMANTIC_GETTER:
660                                 class->properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
661                                 break;
662                         default:
663                                 break;
664                         }
665                 }
666         }
667 }
668
669 static void
670 init_events (MonoClass *class)
671 {
672         guint startm, endm, i, j;
673         guint32 cols [MONO_EVENT_SIZE];
674         MonoTableInfo *pt = &class->image->tables [MONO_TABLE_EVENT];
675         MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
676
677         class->event.first = mono_metadata_events_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->event.last);
678         class->event.count = class->event.last - class->event.first;
679
680         class->events = g_new0 (MonoEvent, class->event.count);
681         for (i = class->event.first; i < class->event.last; ++i) {
682                 mono_metadata_decode_row (pt, i, cols, MONO_EVENT_SIZE);
683                 class->events [i - class->event.first].parent = class;
684                 class->events [i - class->event.first].attrs = cols [MONO_EVENT_FLAGS];
685                 class->events [i - class->event.first].name = mono_metadata_string_heap (class->image, cols [MONO_EVENT_NAME]);
686
687                 startm = mono_metadata_methods_from_event (class->image, i, &endm);
688                 for (j = startm; j < endm; ++j) {
689                         mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
690                         switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
691                         case METHOD_SEMANTIC_ADD_ON:
692                                 class->events [i - class->event.first].add = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
693                                 break;
694                         case METHOD_SEMANTIC_REMOVE_ON:
695                                 class->events [i - class->event.first].remove = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
696                                 break;
697                         case METHOD_SEMANTIC_FIRE:
698                                 class->events [i - class->event.first].raise = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
699                                 break;
700                         case METHOD_SEMANTIC_OTHER: /* don't care for now */
701                         default:
702                                 break;
703                         }
704                 }
705         }
706 }
707
708 static guint
709 mono_get_unique_iid (MonoClass *class)
710 {
711         static GHashTable *iid_hash = NULL;
712         static guint iid = 0;
713
714         char *str;
715         gpointer value;
716         
717         g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
718
719         mono_loader_lock ();
720
721         if (!iid_hash)
722                 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
723
724         str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
725
726         if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
727                 mono_loader_unlock ();
728                 g_free (str);
729                 return (guint)value;
730         } else {
731                 g_hash_table_insert (iid_hash, str, (gpointer)iid);
732                 ++iid;
733         }
734
735         mono_loader_unlock ();
736
737         return iid - 1;
738 }
739
740 static void
741 collect_implemented_interfaces_aux (MonoClass *klass, GPtrArray **res)
742 {
743         int i;
744         MonoClass *ic;
745         
746         for (i = 0; i < klass->interface_count; i++) {
747                 ic = klass->interfaces [i];
748
749                 if (*res == NULL)
750                         *res = g_ptr_array_new ();
751                 g_ptr_array_add (*res, ic);
752
753                 collect_implemented_interfaces_aux (ic, res);
754         }
755 }
756
757 static inline GPtrArray*
758 collect_implemented_interfaces (MonoClass *klass)
759 {
760         GPtrArray *res = NULL;
761
762         collect_implemented_interfaces_aux (klass, &res);
763         return res;
764 }
765
766 static int
767 setup_interface_offsets (MonoClass *class, int cur_slot)
768 {
769         MonoClass *k, *ic;
770         int i, max_iid;
771         GPtrArray *ifaces;
772
773         /* compute maximum number of slots and maximum interface id */
774         max_iid = 0;
775         for (k = class; k ; k = k->parent) {
776                 for (i = 0; i < k->interface_count; i++) {
777                         ic = k->interfaces [i];
778
779                         if (!ic->inited)
780                                 mono_class_init (ic);
781
782                         if (max_iid < ic->interface_id)
783                                 max_iid = ic->interface_id;
784                 }
785         }
786
787         if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
788                 if (max_iid < class->interface_id)
789                         max_iid = class->interface_id;
790         }
791         class->max_interface_id = max_iid;
792         /* compute vtable offset for interfaces */
793         class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
794
795         for (i = 0; i <= max_iid; i++)
796                 class->interface_offsets [i] = -1;
797
798         ifaces = collect_implemented_interfaces (class);
799         if (ifaces) {
800                 for (i = 0; i < ifaces->len; ++i) {
801                         ic = g_ptr_array_index (ifaces, i);
802                         class->interface_offsets [ic->interface_id] = cur_slot;
803                         cur_slot += ic->method.count;
804                 }
805                 g_ptr_array_free (ifaces, TRUE);
806         }
807
808         for (k = class->parent; k ; k = k->parent) {
809                 ifaces = collect_implemented_interfaces (k);
810                 if (ifaces) {
811                         for (i = 0; i < ifaces->len; ++i) {
812                                 ic = g_ptr_array_index (ifaces, i);
813
814                                 if (class->interface_offsets [ic->interface_id] == -1) {
815                                         int io = k->interface_offsets [ic->interface_id];
816
817                                         g_assert (io >= 0);
818
819                                         class->interface_offsets [ic->interface_id] = io;
820                                 }
821                         }
822                         g_ptr_array_free (ifaces, TRUE);
823                 }
824         }
825
826         if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
827                 class->interface_offsets [class->interface_id] = cur_slot;
828
829         return cur_slot;
830 }
831
832 void
833 mono_class_setup_vtable (MonoClass *class, MonoMethod **overrides, int onum)
834 {
835         MonoClass *k, *ic;
836         MonoMethod **vtable;
837         int i, max_vtsize = 0, max_iid, cur_slot = 0;
838         GPtrArray *ifaces;
839         MonoGHashTable *override_map = NULL;
840
841         /* setup_vtable() must be called only once on the type */
842         if (class->interface_offsets) {
843                 g_warning ("vtable already computed in %s.%s", class->name_space, class->name);
844                 return;
845         }
846
847         ifaces = collect_implemented_interfaces (class);
848         if (ifaces) {
849                 for (i = 0; i < ifaces->len; i++) {
850                         MonoClass *ic = g_ptr_array_index (ifaces, i);
851                         max_vtsize += ic->method.count;
852                 }
853                 g_ptr_array_free (ifaces, TRUE);
854         }
855         
856         if (class->parent) {
857                 max_vtsize += class->parent->vtable_size;
858                 cur_slot = class->parent->vtable_size;
859         }
860
861         max_vtsize += class->method.count;
862
863         vtable = alloca (sizeof (gpointer) * max_vtsize);
864         memset (vtable, 0, sizeof (gpointer) * max_vtsize);
865
866         /* printf ("METAINIT %s.%s\n", class->name_space, class->name); */
867
868         cur_slot = setup_interface_offsets (class, cur_slot);
869         max_iid = class->max_interface_id;
870
871         if (class->parent && class->parent->vtable_size)
872                 memcpy (vtable, class->parent->vtable,  sizeof (gpointer) * class->parent->vtable_size);
873
874         /* override interface methods */
875         for (i = 0; i < onum; i++) {
876                 MonoMethod *decl = overrides [i*2];
877                 if (decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
878                         int dslot;
879                         g_assert (decl->slot != -1);
880                         dslot = decl->slot + class->interface_offsets [decl->klass->interface_id];
881                         vtable [dslot] = overrides [i*2 + 1];
882                         vtable [dslot]->slot = dslot;
883                         if (!override_map)
884                                 override_map = mono_g_hash_table_new (NULL, NULL);
885
886                         mono_g_hash_table_insert (override_map, overrides [i * 2], overrides [i * 2 + 1]);
887                 }
888         }
889
890         for (k = class; k ; k = k->parent) {
891                 int nifaces = 0;
892                 ifaces = collect_implemented_interfaces (k);
893                 if (ifaces)
894                         nifaces = ifaces->len;
895                 for (i = 0; i < nifaces; i++) {
896                         int j, l, io;
897
898                         ic = g_ptr_array_index (ifaces, i);
899                         io = k->interface_offsets [ic->interface_id];
900
901                         g_assert (io >= 0);
902                         g_assert (io <= max_vtsize);
903
904                         if (k == class) {
905                                 for (l = 0; l < ic->method.count; l++) {
906                                         MonoMethod *im = ic->methods [l];                                               
907
908                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
909                                                 continue;
910
911                                         for (j = 0; j < class->method.count; ++j) {
912                                                 MonoMethod *cm = class->methods [j];
913                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
914                                                     !((cm->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) ||
915                                                     !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
916                                                         continue;
917                                                 if (!strcmp(cm->name, im->name) && 
918                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
919                                                         g_assert (io + l <= max_vtsize);
920                                                         vtable [io + l] = cm;
921                                                 }
922                                         }
923                                 }
924                         } else {
925                                 /* already implemented */
926                                 if (io >= k->vtable_size)
927                                         continue;
928                         }
929                                 
930                         for (l = 0; l < ic->method.count; l++) {
931                                 MonoMethod *im = ic->methods [l];                                               
932                                 MonoClass *k1;
933
934                                 g_assert (io + l <= max_vtsize);
935
936                                 if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
937                                         continue;
938                                         
939                                 for (k1 = class; k1; k1 = k1->parent) {
940                                         for (j = 0; j < k1->method.count; ++j) {
941                                                 MonoMethod *cm = k1->methods [j];
942
943                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
944                                                     !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
945                                                         continue;
946                                                 
947                                                 if (!strcmp(cm->name, im->name) && 
948                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
949                                                         g_assert (io + l <= max_vtsize);
950                                                         vtable [io + l] = cm;
951                                                         break;
952                                                 }
953                                                 
954                                         }
955                                         g_assert (io + l <= max_vtsize);
956                                         if (vtable [io + l] && !(vtable [io + l]->flags & METHOD_ATTRIBUTE_ABSTRACT))
957                                                 break;
958                                 }
959                         }
960
961                         for (l = 0; l < ic->method.count; l++) {
962                                 MonoMethod *im = ic->methods [l];                                               
963                                 char *qname, *fqname;
964                                 MonoClass *k1;
965                                 
966                                 if (vtable [io + l])
967                                         continue;
968                                         
969                                 qname = g_strconcat (ic->name, ".", im->name, NULL); 
970                                 if (ic->name_space && ic->name_space [0])
971                                         fqname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
972                                 else
973                                         fqname = NULL;
974
975                                 for (k1 = class; k1; k1 = k1->parent) {
976                                         for (j = 0; j < k1->method.count; ++j) {
977                                                 MonoMethod *cm = k1->methods [j];
978
979                                                 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
980                                                         continue;
981                                         
982                                                 if (((fqname && !strcmp (cm->name, fqname)) || !strcmp (cm->name, qname)) &&
983                                                     mono_metadata_signature_equal (cm->signature, im->signature)) {
984                                                         g_assert (io + l <= max_vtsize);
985                                                         vtable [io + l] = cm;
986                                                         break;
987                                                 }
988                                         }
989                                 }
990                                 g_free (qname);
991                                 g_free (fqname);
992                         }
993
994                         
995                         if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
996                                 for (l = 0; l < ic->method.count; l++) {
997                                         char *msig;
998                                         MonoMethod *im = ic->methods [l];
999                                         if (im->flags & METHOD_ATTRIBUTE_STATIC)
1000                                                         continue;
1001                                         g_assert (io + l <= max_vtsize);
1002
1003                                         /* 
1004                                          * If one of our parents already implements this interface
1005                                          * we can inherit the implementation.
1006                                          */
1007                                         if (!(vtable [io + l])) {
1008                                                 MonoClass *parent = class->parent;
1009
1010                                                 if ((ic->interface_id <= parent->max_interface_id) && 
1011                                                         (parent->interface_offsets [ic->interface_id]) &&
1012                                                         parent->vtable)
1013                                                         vtable [io + l] = parent->vtable [parent->interface_offsets [ic->interface_id] + l];
1014                                         }
1015
1016                                         if (!(vtable [io + l])) {
1017                                                 for (j = 0; j < onum; ++j) {
1018                                                         g_print (" at slot %d: %s (%d) overrides %s (%d)\n", io+l, overrides [j*2+1]->name, 
1019                                                                  overrides [j*2+1]->slot, overrides [j*2]->name, overrides [j*2]->slot);
1020                                                 }
1021                                                 msig = mono_signature_get_desc (im->signature, FALSE);
1022                                                 printf ("no implementation for interface method %s.%s::%s(%s) in class %s.%s\n",
1023                                                         ic->name_space, ic->name, im->name, msig, class->name_space, class->name);
1024                                                 g_free (msig);
1025                                                 for (j = 0; j < class->method.count; ++j) {
1026                                                         MonoMethod *cm = class->methods [j];
1027                                                         msig = mono_signature_get_desc (cm->signature, FALSE);
1028                                                         
1029                                                         printf ("METHOD %s(%s)\n", cm->name, msig);
1030                                                         g_free (msig);
1031                                                 }
1032                                                 g_assert_not_reached ();
1033                                         }
1034                                 }
1035                         }
1036                 
1037                         for (l = 0; l < ic->method.count; l++) {
1038                                 MonoMethod *im = vtable [io + l];
1039
1040                                 if (im) {
1041                                         g_assert (io + l <= max_vtsize);
1042                                         if (im->slot < 0) {
1043                                                 /* FIXME: why do we need this ? */
1044                                                 im->slot = io + l;
1045                                                 /* g_assert_not_reached (); */
1046                                         }
1047                                 }
1048                         }
1049                 }
1050                 if (ifaces)
1051                         g_ptr_array_free (ifaces, TRUE);
1052         } 
1053
1054         for (i = 0; i < class->method.count; ++i) {
1055                 MonoMethod *cm;
1056                
1057                 cm = class->methods [i];
1058
1059                 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT) && (cm->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
1060                         int slot = -1;
1061                         for (k = class->parent; k ; k = k->parent) {
1062                                 int j;
1063                                 for (j = 0; j < k->method.count; ++j) {
1064                                         MonoMethod *m1 = k->methods [j];
1065                                         if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
1066                                                 continue;
1067                                         if (!strcmp(cm->name, m1->name) && 
1068                                             mono_metadata_signature_equal (cm->signature, m1->signature)) {
1069                                                 slot = k->methods [j]->slot;
1070                                                 g_assert (cm->slot < max_vtsize);
1071                                                 if (!override_map)
1072                                                         override_map = mono_g_hash_table_new (NULL, NULL);
1073                                                 mono_g_hash_table_insert (override_map, m1, cm);
1074                                                 break;
1075                                         }
1076                                 }
1077                                 if (slot >= 0) 
1078                                         break;
1079                         }
1080                         if (slot >= 0)
1081                                 cm->slot = slot;
1082                 }
1083
1084                 if (cm->slot < 0)
1085                         cm->slot = cur_slot++;
1086
1087                 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT) && !cm->signature->generic_param_count)
1088                         vtable [cm->slot] = cm;
1089         }
1090
1091         /* override non interface methods */
1092         for (i = 0; i < onum; i++) {
1093                 MonoMethod *decl = overrides [i*2];
1094                 if (!(decl->klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1095                         g_assert (decl->slot != -1);
1096                         vtable [decl->slot] = overrides [i*2 + 1];
1097                         overrides [i * 2 + 1]->slot = decl->slot;
1098                         if (!override_map)
1099                                 override_map = mono_g_hash_table_new (NULL, NULL);
1100                         mono_g_hash_table_insert (override_map, decl, overrides [i * 2 + 1]);
1101                 }
1102         }
1103
1104         /*
1105          * If a method occupies more than one place in the vtable, and it is
1106          * overriden, then change the other occurances too.
1107          */
1108         if (override_map) {
1109                 for (i = 0; i < max_vtsize; ++i)
1110                         if (vtable [i]) {
1111                                 MonoMethod *cm = mono_g_hash_table_lookup (override_map, vtable [i]);
1112                                 if (cm)
1113                                         vtable [i] = cm;
1114                         }
1115
1116                 mono_g_hash_table_destroy (override_map);
1117         }
1118        
1119         class->vtable_size = cur_slot;
1120         class->vtable = g_malloc0 (sizeof (gpointer) * class->vtable_size);
1121         memcpy (class->vtable, vtable,  sizeof (gpointer) * class->vtable_size);
1122
1123         if (mono_print_vtable) {
1124                 int icount = 0;
1125
1126                 for (i = 0; i <= max_iid; i++)
1127                         if (class->interface_offsets [i] != -1)
1128                                 icount++;
1129
1130                 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space, 
1131                         class->name, class->vtable_size, icount); 
1132
1133                 for (i = 0; i < class->vtable_size; ++i) {
1134                         MonoMethod *cm;
1135                
1136                         cm = vtable [i];
1137                         if (cm) {
1138                                 printf ("  slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
1139                                         cm->klass->name_space, cm->klass->name,
1140                                         cm->name);
1141                         }
1142                 }
1143
1144
1145                 if (icount) {
1146                         printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space, 
1147                                 class->name, max_iid);
1148         
1149                         for (i = 0; i < class->interface_count; i++) {
1150                                 ic = class->interfaces [i];
1151                                 printf ("  slot %03d(%03d) %s.%s\n",  
1152                                         class->interface_offsets [ic->interface_id],
1153                                         ic->method.count, ic->name_space, ic->name);
1154                         }
1155
1156                         for (k = class->parent; k ; k = k->parent) {
1157                                 for (i = 0; i < k->interface_count; i++) {
1158                                         ic = k->interfaces [i]; 
1159                                         printf ("  slot %03d(%03d) %s.%s\n", 
1160                                                 class->interface_offsets [ic->interface_id],
1161                                                 ic->method.count, ic->name_space, ic->name);
1162                                 }
1163                         }
1164                 }
1165         }
1166 }
1167
1168 static MonoMethod *
1169 inflate_method (MonoGenericInst *ginst, MonoMethod *method)
1170 {
1171         MonoGenericMethod *gmethod = g_new0 (MonoGenericMethod, 1);
1172
1173         gmethod->generic_method = method;
1174         gmethod->generic_inst = ginst;
1175
1176         return mono_class_inflate_generic_method (method, gmethod, ginst->klass);
1177 }
1178
1179 /**
1180  * mono_class_init:
1181  * @class: the class to initialize
1182  *
1183  * compute the instance_size, class_size and other infos that cannot be 
1184  * computed at mono_class_get() time. Also compute a generic vtable and 
1185  * the method slot numbers. We use this infos later to create a domain
1186  * specific vtable.  
1187  */
1188 void
1189 mono_class_init (MonoClass *class)
1190 {
1191         int i;
1192         static MonoMethod *default_ghc = NULL;
1193         static MonoMethod *default_finalize = NULL;
1194         static int finalize_slot = -1;
1195         static int ghc_slot = -1;
1196         MonoMethod **overrides;
1197         int onum = 0;
1198
1199         g_assert (class);
1200
1201         if (class->inited)
1202                 return;
1203
1204         /*g_print ("Init class %s\n", class->name);*/
1205
1206         /* We do everything inside the lock to prevent races */
1207         mono_loader_lock ();
1208
1209         if (class->inited) {
1210                 mono_loader_unlock ();
1211                 /* Somebody might have gotten in before us */
1212                 return;
1213         }
1214
1215         if (class->init_pending) {
1216                 /* this indicates a cyclic dependency */
1217                 g_error ("pending init %s.%s\n", class->name_space, class->name);
1218         }
1219
1220         class->init_pending = 1;
1221
1222         mono_stats.initialized_class_count++;
1223
1224         if (class->generic_inst && !class->generic_inst->is_dynamic) {
1225                 MonoGenericInst *ginst = class->generic_inst;
1226                 MonoClass *gklass;
1227
1228                 gklass = mono_class_from_mono_type (ginst->generic_type);
1229                 mono_class_init (gklass);
1230
1231                 if (ginst->parent)
1232                         class->parent = mono_class_from_mono_type (ginst->parent);
1233                 else
1234                         class->parent = gklass->parent;
1235
1236                 mono_class_setup_parent (class, class->parent);
1237
1238                 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
1239                         class->interface_id = mono_get_unique_iid (class);
1240
1241                 class->method = gklass->method;
1242                 class->methods = g_new0 (MonoMethod *, class->method.count);
1243
1244                 for (i = 0; i < class->method.count; i++)
1245                         class->methods [i] = inflate_method (ginst, gklass->methods [i]);
1246
1247                 class->field = gklass->field;
1248                 class->fields = g_new0 (MonoClassField, class->field.count);
1249
1250                 for (i = 0; i < class->field.count; i++) {
1251                         class->fields [i] = gklass->fields [i];
1252                         class->fields [i].generic_type = gklass->fields [i].type;
1253                         class->fields [i].parent = class;
1254                         class->fields [i].type = mono_class_inflate_generic_type (
1255                                 class->fields [i].type, ginst, NULL);
1256                 }
1257
1258                 class->property = gklass->property;
1259                 class->properties = g_new0 (MonoProperty, class->property.count);
1260
1261                 for (i = 0; i < class->property.count; i++) {
1262                         MonoProperty *prop = &class->properties [i];
1263
1264                         *prop = gklass->properties [i];
1265
1266                         if (prop->get)
1267                                 prop->get = inflate_method (ginst, prop->get);
1268                         if (prop->set)
1269                                 prop->set = inflate_method (ginst, prop->set);
1270                 }
1271
1272                 class->interface_count = gklass->interface_count;
1273                 class->interfaces = g_new0 (MonoClass *, class->interface_count);
1274                 for (i = 0; i < class->interface_count; i++) {
1275                         MonoType *it = &gklass->interfaces [i]->byval_arg;
1276                         MonoType *inflated = mono_class_inflate_generic_type (it, ginst, NULL);
1277                         class->interfaces [i] = mono_class_from_mono_type (inflated);
1278                         mono_class_init (class->interfaces [i]);
1279                 }
1280         }
1281
1282         if (class->parent && !class->parent->inited)
1283                 mono_class_init (class->parent);
1284
1285         /*
1286          * Computes the size used by the fields, and their locations
1287          */
1288         if (!class->size_inited)
1289                 class_compute_field_layout (class);
1290
1291         /* initialize method pointers */
1292         if (class->rank) {
1293                 MonoMethod *ctor;
1294                 MonoMethodSignature *sig;
1295                 class->method.count = class->rank > 1? 2: 1;
1296                 sig = mono_metadata_signature_alloc (class->image, class->rank);
1297                 sig->ret = &mono_defaults.void_class->byval_arg;
1298                 sig->pinvoke = TRUE;
1299                 for (i = 0; i < class->rank; ++i)
1300                         sig->params [i] = &mono_defaults.int32_class->byval_arg;
1301
1302                 ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1303                 ctor->klass = class;
1304                 ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1305                 ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1306                 ctor->signature = sig;
1307                 ctor->name = ".ctor";
1308                 ctor->slot = -1;
1309                 class->methods = g_new (MonoMethod*, class->method.count);
1310                 class->methods [0] = ctor;
1311                 if (class->rank > 1) {
1312                         sig = mono_metadata_signature_alloc (class->image, class->rank * 2);
1313                         sig->ret = &mono_defaults.void_class->byval_arg;
1314                         sig->pinvoke = TRUE;
1315                         for (i = 0; i < class->rank * 2; ++i)
1316                                 sig->params [i] = &mono_defaults.int32_class->byval_arg;
1317
1318                         ctor = (MonoMethod *) g_new0 (MonoMethodPInvoke, 1);
1319                         ctor->klass = class;
1320                         ctor->flags = METHOD_ATTRIBUTE_PUBLIC | METHOD_ATTRIBUTE_RT_SPECIAL_NAME | METHOD_ATTRIBUTE_SPECIAL_NAME;
1321                         ctor->iflags = METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL;
1322                         ctor->signature = sig;
1323                         ctor->name = ".ctor";
1324                         ctor->slot = -1;
1325                         class->methods [1] = ctor;
1326                 }
1327         } else {
1328                 if (!class->generic_inst && !class->methods) {
1329                         class->methods = g_new (MonoMethod*, class->method.count);
1330                         for (i = 0; i < class->method.count; ++i) {
1331                                 class->methods [i] = mono_get_method (class->image,
1332                                                                       MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
1333                         }
1334                 }
1335         }
1336
1337         init_properties (class);
1338         init_events (class);
1339
1340         i = mono_metadata_nesting_typedef (class->image, class->type_token, 1);
1341         while (i) {
1342                 MonoClass* nclass;
1343                 guint32 cols [MONO_NESTED_CLASS_SIZE];
1344                 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
1345                 nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
1346                 class->nested_classes = g_list_prepend (class->nested_classes, nclass);
1347
1348                 i = mono_metadata_nesting_typedef (class->image, class->type_token, i + 1);
1349         }
1350
1351         mono_class_setup_supertypes (class);
1352
1353         if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
1354                 for (i = 0; i < class->method.count; ++i)
1355                         class->methods [i]->slot = i;
1356                 class->init_pending = 0;
1357                 class->inited = 1;
1358                 /* 
1359                  * class->interface_offsets is needed for the castclass/isinst code, so
1360                  * we have to setup them for interfaces, too.
1361                  */
1362                 setup_interface_offsets (class, 0);
1363                 mono_loader_unlock ();
1364                 return;
1365         }
1366
1367         overrides = mono_class_get_overrides (class->image, class->type_token, &onum);  
1368         mono_class_setup_vtable (class, overrides, onum);
1369         g_free (overrides);
1370
1371         class->inited = 1;
1372         class->init_pending = 0;
1373
1374         if (!default_ghc) {
1375                 if (class == mono_defaults.object_class) { 
1376                        
1377                         for (i = 0; i < class->vtable_size; ++i) {
1378                                 MonoMethod *cm = class->vtable [i];
1379                
1380                                 if (!strcmp (cm->name, "GetHashCode")) {
1381                                         ghc_slot = i;
1382                                         break;
1383                                 }
1384                         }
1385
1386                         g_assert (ghc_slot > 0);
1387
1388                         default_ghc = class->vtable [ghc_slot];
1389                 }
1390         }
1391         
1392         class->ghcimpl = 1;
1393         if (class->parent) { 
1394
1395                 if (class->vtable [ghc_slot] == default_ghc) {
1396                         class->ghcimpl = 0;
1397                 }
1398         }
1399
1400         if (!default_finalize) {
1401                 if (class == mono_defaults.object_class) { 
1402                        
1403                         for (i = 0; i < class->vtable_size; ++i) {
1404                                 MonoMethod *cm = class->vtable [i];
1405                
1406                                 if (!strcmp (cm->name, "Finalize")) {
1407                                         finalize_slot = i;
1408                                         break;
1409                                 }
1410                         }
1411
1412                         g_assert (finalize_slot > 0);
1413
1414                         default_finalize = class->vtable [finalize_slot];
1415                 }
1416         }
1417
1418         /* Object::Finalize should have empty implemenatation */
1419         class->has_finalize = 0;
1420         if (class->parent) { 
1421                 if (class->vtable [finalize_slot] != default_finalize)
1422                         class->has_finalize = 1;
1423         }
1424
1425         mono_loader_unlock ();
1426
1427         if (mono_debugger_class_init_func)
1428                 mono_debugger_class_init_func (class);
1429 }
1430
1431
1432 void
1433 mono_class_setup_mono_type (MonoClass *class)
1434 {
1435         const char *name = class->name;
1436         const char *nspace = class->name_space;
1437
1438         if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
1439                 class->interface_id = mono_get_unique_iid (class);
1440
1441         class->this_arg.byref = 1;
1442         class->this_arg.data.klass = class;
1443         class->this_arg.type = MONO_TYPE_CLASS;
1444         class->byval_arg.data.klass = class;
1445         class->byval_arg.type = MONO_TYPE_CLASS;
1446
1447         if (!strcmp (nspace, "System")) {
1448                 if (!strcmp (name, "ValueType")) {
1449                         /*
1450                          * do not set the valuetype bit for System.ValueType.
1451                          * class->valuetype = 1;
1452                          */
1453                 } else if (!strcmp (name, "Enum")) {
1454                         /*
1455                          * do not set the valuetype bit for System.Enum.
1456                          * class->valuetype = 1;
1457                          */
1458                         class->valuetype = 0;
1459                         class->enumtype = 0;
1460                 } else if (!strcmp (name, "Object")) {
1461                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
1462                 } else if (!strcmp (name, "String")) {
1463                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
1464                 } else if (!strcmp (name, "TypedReference")) {
1465                         class->this_arg.type = class->byval_arg.type = MONO_TYPE_TYPEDBYREF;
1466                 }
1467         }
1468         
1469         if (class->valuetype) {
1470                 int t = MONO_TYPE_VALUETYPE;
1471                 if (!strcmp (nspace, "System")) {
1472                         switch (*name) {
1473                         case 'B':
1474                                 if (!strcmp (name, "Boolean")) {
1475                                         t = MONO_TYPE_BOOLEAN;
1476                                 } else if (!strcmp(name, "Byte")) {
1477                                         t = MONO_TYPE_U1;
1478                                         class->blittable = TRUE;                                                
1479                                 }
1480                                 break;
1481                         case 'C':
1482                                 if (!strcmp (name, "Char")) {
1483                                         t = MONO_TYPE_CHAR;
1484                                 }
1485                                 break;
1486                         case 'D':
1487                                 if (!strcmp (name, "Double")) {
1488                                         t = MONO_TYPE_R8;
1489                                         class->blittable = TRUE;                                                
1490                                 }
1491                                 break;
1492                         case 'I':
1493                                 if (!strcmp (name, "Int32")) {
1494                                         t = MONO_TYPE_I4;
1495                                         class->blittable = TRUE;
1496                                 } else if (!strcmp(name, "Int16")) {
1497                                         t = MONO_TYPE_I2;
1498                                         class->blittable = TRUE;
1499                                 } else if (!strcmp(name, "Int64")) {
1500                                         t = MONO_TYPE_I8;
1501                                         class->blittable = TRUE;
1502                                 } else if (!strcmp(name, "IntPtr")) {
1503                                         t = MONO_TYPE_I;
1504                                         class->blittable = TRUE;
1505                                 }
1506                                 break;
1507                         case 'S':
1508                                 if (!strcmp (name, "Single")) {
1509                                         t = MONO_TYPE_R4;
1510                                         class->blittable = TRUE;                                                
1511                                 } else if (!strcmp(name, "SByte")) {
1512                                         t = MONO_TYPE_I1;
1513                                         class->blittable = TRUE;
1514                                 }
1515                                 break;
1516                         case 'U':
1517                                 if (!strcmp (name, "UInt32")) {
1518                                         t = MONO_TYPE_U4;
1519                                         class->blittable = TRUE;
1520                                 } else if (!strcmp(name, "UInt16")) {
1521                                         t = MONO_TYPE_U2;
1522                                         class->blittable = TRUE;
1523                                 } else if (!strcmp(name, "UInt64")) {
1524                                         t = MONO_TYPE_U8;
1525                                         class->blittable = TRUE;
1526                                 } else if (!strcmp(name, "UIntPtr")) {
1527                                         t = MONO_TYPE_U;
1528                                         class->blittable = TRUE;
1529                                 }
1530                                 break;
1531                         case 'T':
1532                                 if (!strcmp (name, "TypedReference")) {
1533                                         t = MONO_TYPE_TYPEDBYREF;
1534                                         class->blittable = TRUE;
1535                                 }
1536                                 break;
1537                         case 'V':
1538                                 if (!strcmp (name, "Void")) {
1539                                         t = MONO_TYPE_VOID;
1540                                 }
1541                                 break;
1542                         default:
1543                                 break;
1544                         }
1545                 }
1546                 class->this_arg.type = class->byval_arg.type = t;
1547         }
1548 }
1549
1550 void
1551 mono_class_setup_parent (MonoClass *class, MonoClass *parent)
1552 {
1553         gboolean system_namespace;
1554
1555         system_namespace = !strcmp (class->name_space, "System");
1556
1557         /* if root of the hierarchy */
1558         if (system_namespace && !strcmp (class->name, "Object")) {
1559                 class->parent = NULL;
1560                 class->instance_size = sizeof (MonoObject);
1561                 return;
1562         }
1563         if (!strcmp (class->name, "<Module>")) {
1564                 class->parent = NULL;
1565                 class->instance_size = 0;
1566                 return;
1567         }
1568
1569         if (!(class->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1570                 class->parent = parent;
1571
1572                 if (!parent)
1573                         g_assert_not_reached (); /* FIXME */
1574
1575                 if (parent->generic_inst && !parent->name) {
1576                         /*
1577                          * If the parent is a generic instance, we may get
1578                          * called before it is fully initialized, especially
1579                          * before it has its name.
1580                          */
1581                         return;
1582                 }
1583
1584                 class->marshalbyref = parent->marshalbyref;
1585                 class->contextbound  = parent->contextbound;
1586                 class->delegate  = parent->delegate;
1587                 
1588                 if (system_namespace) {
1589                         if (*class->name == 'M' && !strcmp (class->name, "MarshalByRefObject"))
1590                                 class->marshalbyref = 1;
1591
1592                         if (*class->name == 'C' && !strcmp (class->name, "ContextBoundObject")) 
1593                                 class->contextbound  = 1;
1594
1595                         if (*class->name == 'D' && !strcmp (class->name, "Delegate")) 
1596                                 class->delegate  = 1;
1597                 }
1598
1599                 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && 
1600                                                 (strcmp (class->parent->name_space, "System") == 0)))
1601                         class->valuetype = 1;
1602                 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
1603                         class->valuetype = class->enumtype = 1;
1604                 }
1605                 /*class->enumtype = class->parent->enumtype; */
1606                 mono_class_setup_supertypes (class);
1607         } else {
1608                 class->parent = NULL;
1609         }
1610
1611 }
1612
1613 void
1614 mono_class_setup_supertypes (MonoClass *class)
1615 {
1616         MonoClass *k;
1617         int ms, i;
1618
1619         if (class->supertypes)
1620                 return;
1621
1622         class->idepth = 0;
1623         for (k = class; k ; k = k->parent) {
1624                 class->idepth++;
1625         }
1626
1627         ms = MAX (MONO_DEFAULT_SUPERTABLE_SIZE, class->idepth);
1628         class->supertypes = g_new0 (MonoClass *, ms);
1629
1630         if (class->parent) {
1631                 for (i = class->idepth, k = class; k ; k = k->parent)
1632                         class->supertypes [--i] = k;
1633         } else {
1634                 class->supertypes [0] = class;
1635         }
1636 }       
1637
1638 /**
1639  * @image: context where the image is created
1640  * @type_token:  typedef token
1641  */
1642 static MonoClass *
1643 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
1644 {
1645         MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
1646         MonoClass *class, *parent = NULL;
1647         guint32 cols [MONO_TYPEDEF_SIZE];
1648         guint32 cols_next [MONO_TYPEDEF_SIZE];
1649         guint tidx = mono_metadata_token_index (type_token);
1650         const char *name, *nspace;
1651         guint icount = 0; 
1652         MonoClass **interfaces;
1653
1654         mono_loader_lock ();
1655
1656         if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token)))) {
1657                 mono_loader_unlock ();
1658                 return class;
1659         }
1660
1661         g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
1662         
1663         mono_metadata_decode_row (tt, tidx - 1, cols, MONO_TYPEDEF_SIZE);
1664         
1665         name = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
1666         nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
1667
1668         if (cols [MONO_TYPEDEF_EXTENDS])
1669                 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [MONO_TYPEDEF_EXTENDS]));
1670         interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
1671
1672         class = g_malloc0 (sizeof (MonoClass));
1673                            
1674         g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
1675
1676         class->interfaces = interfaces;
1677         class->interface_count = icount;
1678
1679         class->name = name;
1680         class->name_space = nspace;
1681
1682         class->image = image;
1683         class->type_token = type_token;
1684         class->flags = cols [MONO_TYPEDEF_FLAGS];
1685
1686         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_UNICODE_CLASS)
1687                 class->unicode = 1;
1688         /* fixme: maybe we must set this on windows 
1689         if ((class->flags & TYPE_ATTRIBUTE_STRING_FORMAT_MASK) == TYPE_ATTRIBUTE_AUTO_CLASS)
1690                 class->unicode = 1;
1691         */
1692
1693         class->cast_class = class->element_class = class;
1694
1695         /*g_print ("Load class %s\n", name);*/
1696
1697         mono_class_setup_parent (class, parent);
1698
1699         mono_class_setup_mono_type (class);
1700
1701         /*
1702          * Compute the field and method lists
1703          */
1704         class->field.first  = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
1705         class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
1706
1707         if (tt->rows > tidx){           
1708                 mono_metadata_decode_row (tt, tidx, cols_next, MONO_TYPEDEF_SIZE);
1709                 class->field.last  = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
1710                 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
1711         } else {
1712                 class->field.last  = image->tables [MONO_TABLE_FIELD].rows;
1713                 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
1714         }
1715
1716         if (cols [MONO_TYPEDEF_FIELD_LIST] && 
1717             cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
1718                 class->field.count = class->field.last - class->field.first;
1719         else
1720                 class->field.count = 0;
1721
1722         if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
1723                 class->method.count = class->method.last - class->method.first;
1724         else
1725                 class->method.count = 0;
1726
1727         /* reserve space to store vector pointer in arrays */
1728         if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
1729                 class->instance_size += 2 * sizeof (gpointer);
1730                 g_assert (class->field.count == 0);
1731         }
1732
1733         if (class->enumtype)
1734                 class_compute_field_layout (class);
1735
1736         if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
1737                 class->nested_in = mono_class_create_from_typedef (image, type_token);
1738
1739         class->gen_params = mono_metadata_load_generic_params (image, class->type_token, &icount);
1740         class->num_gen_params = icount;
1741
1742         mono_loader_unlock ();
1743
1744         return class;
1745 }
1746
1747 char*
1748 _mono_class_get_instantiation_name (const char *name, MonoGenericInst *ginst, int offset)
1749 {
1750         GString *res = g_string_new (name);
1751         const char *p;
1752         int count, i;
1753         MonoClass *argclass;
1754         
1755         p = strchr (name, '<');
1756         count = ginst->type_argc - offset;
1757         if (p) {
1758                 g_string_truncate (res, (p - name) + 1);
1759         } else if (count) {
1760                 g_string_append_c (res, '<');
1761         }
1762         for (i = offset; i < ginst->type_argc; ++i) {
1763                 if (i > offset)
1764                         g_string_append_c (res, ',');
1765                 argclass = mono_class_from_mono_type (ginst->type_argv [i]);
1766                 g_string_append (res, argclass->name);
1767         }
1768         if (count)
1769                 g_string_append_c (res, '>');
1770         return g_string_free (res, FALSE);
1771 }
1772
1773 MonoClass*
1774 mono_class_create_generic (MonoGenericInst *ginst)
1775 {
1776         MonoClass *klass, *gklass;
1777
1778         if (!ginst->klass)
1779                 ginst->klass = g_malloc0 (sizeof (MonoClass));
1780         klass = ginst->klass;
1781
1782         gklass = mono_class_from_mono_type (ginst->generic_type);
1783
1784         if (ginst->nested_in) {
1785                 MonoGenericInst *nginst = ginst->nested_in->data.generic_inst;
1786                 int offset = nginst->type_argc;
1787
1788                 klass->name = _mono_class_get_instantiation_name (gklass->name, ginst, nginst->type_argc);
1789         } else if (!ginst->init_pending)
1790                 klass->name = _mono_class_get_instantiation_name (gklass->name, ginst, 0);
1791         else
1792                 klass->name = gklass->name;
1793         klass->name_space = gklass->name_space;
1794         klass->image = gklass->image;
1795         klass->flags = gklass->flags;
1796
1797         klass->generic_inst = ginst;
1798
1799         klass->this_arg.type = klass->byval_arg.type = MONO_TYPE_GENERICINST;
1800         klass->this_arg.data.generic_inst = klass->byval_arg.data.generic_inst = ginst;
1801         klass->this_arg.byref = TRUE;
1802
1803         klass->cast_class = klass->element_class = klass;
1804
1805         if (ginst->is_dynamic) {
1806                 klass->instance_size = gklass->instance_size;
1807                 klass->class_size = gklass->class_size;
1808                 klass->size_inited = 1;
1809
1810                 klass->valuetype = gklass->valuetype;
1811         }
1812
1813         return klass;
1814 }
1815
1816 MonoClass *
1817 mono_class_from_generic_parameter (MonoGenericParam *param, MonoImage *image, gboolean is_mvar)
1818 {
1819         MonoClass *klass, **ptr;
1820         int count, pos, i;
1821
1822         if (param->pklass)
1823                 return param->pklass;
1824
1825         klass = param->pklass = g_new0 (MonoClass, 1);
1826
1827         for (count = 0, ptr = param->constraints; ptr && *ptr; ptr++, count++)
1828                 ;
1829
1830         pos = 0;
1831         if ((count > 0) && !(param->constraints [0]->flags & TYPE_ATTRIBUTE_INTERFACE)) {
1832                 klass->parent = param->constraints [0];
1833                 pos++;
1834         } else
1835                 klass->parent = mono_defaults.object_class;
1836
1837         if (count - pos > 0) {
1838                 klass->interface_count = count - pos;
1839                 klass->interfaces = g_new0 (MonoClass *, count - pos);
1840                 for (i = pos; i < count; i++)
1841                         klass->interfaces [i - pos] = param->constraints [i];
1842         }
1843
1844         klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
1845         klass->name_space = "";
1846         klass->image = image;
1847         klass->cast_class = klass->element_class = klass;
1848         klass->enum_basetype = &klass->element_class->byval_arg;
1849         klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
1850
1851         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
1852         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
1853         klass->this_arg.byref = TRUE;
1854
1855         mono_class_init (klass);
1856
1857         return klass;
1858 }
1859
1860 static MonoClass *
1861 my_mono_class_from_generic_parameter (MonoGenericParam *param, gboolean is_mvar)
1862 {
1863         MonoClass *klass;
1864
1865         if (param->pklass)
1866                 return param->pklass;
1867
1868         klass = g_new0 (MonoClass, 1);
1869
1870         klass->name = g_strdup_printf (is_mvar ? "!!%d" : "!%d", param->num);
1871         klass->name_space = "";
1872         klass->image = mono_defaults.corlib;
1873         klass->cast_class = klass->element_class = klass;
1874         klass->enum_basetype = &klass->element_class->byval_arg;
1875         klass->flags = TYPE_ATTRIBUTE_INTERFACE | TYPE_ATTRIBUTE_PUBLIC;
1876
1877         klass->this_arg.type = klass->byval_arg.type = is_mvar ? MONO_TYPE_MVAR : MONO_TYPE_VAR;
1878         klass->this_arg.data.generic_param = klass->byval_arg.data.generic_param = param;
1879         klass->this_arg.byref = TRUE;
1880
1881         mono_class_init (klass);
1882
1883         return klass;
1884 }
1885
1886 MonoClass *
1887 mono_ptr_class_get (MonoType *type)
1888 {
1889         MonoClass *result;
1890         MonoClass *el_class;
1891         static GHashTable *ptr_hash = NULL;
1892
1893         mono_loader_lock ();
1894
1895         if (!ptr_hash)
1896                 ptr_hash = g_hash_table_new (NULL, NULL);
1897         el_class = mono_class_from_mono_type (type);
1898         if ((result = g_hash_table_lookup (ptr_hash, el_class))) {
1899                 mono_loader_unlock ();
1900                 return result;
1901         }
1902         result = g_new0 (MonoClass, 1);
1903
1904         result->parent = NULL; /* no parent for PTR types */
1905         result->name = "System";
1906         result->name_space = "MonoPtrFakeClass";
1907         result->image = el_class->image;
1908         result->inited = TRUE;
1909         result->flags = TYPE_ATTRIBUTE_CLASS | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
1910         /* Can pointers get boxed? */
1911         result->instance_size = sizeof (gpointer);
1912         result->cast_class = result->element_class = el_class;
1913         result->enum_basetype = &result->element_class->byval_arg;
1914
1915         result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
1916         result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
1917         result->this_arg.byref = TRUE;
1918
1919         mono_class_setup_supertypes (result);
1920
1921         g_hash_table_insert (ptr_hash, el_class, result);
1922
1923         mono_loader_unlock ();
1924
1925         return result;
1926 }
1927
1928 static MonoClass *
1929 mono_fnptr_class_get (MonoMethodSignature *sig)
1930 {
1931         MonoClass *result;
1932         static GHashTable *ptr_hash = NULL;
1933
1934         mono_loader_lock ();
1935
1936         if (!ptr_hash)
1937                 ptr_hash = g_hash_table_new (NULL, NULL);
1938         
1939         if ((result = g_hash_table_lookup (ptr_hash, sig))) {
1940                 mono_loader_unlock ();
1941                 return result;
1942         }
1943         result = g_new0 (MonoClass, 1);
1944
1945         result->parent = NULL; /* no parent for PTR types */
1946         result->name = "System";
1947         result->name_space = "MonoFNPtrFakeClass";
1948         result->image = NULL; /* need to fix... */
1949         result->inited = TRUE;
1950         result->flags = TYPE_ATTRIBUTE_CLASS; // | (el_class->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
1951         /* Can pointers get boxed? */
1952         result->instance_size = sizeof (gpointer);
1953         result->cast_class = result->element_class = result;
1954
1955         result->this_arg.type = result->byval_arg.type = MONO_TYPE_FNPTR;
1956         result->this_arg.data.method = result->byval_arg.data.method = sig;
1957         result->this_arg.byref = TRUE;
1958         result->enum_basetype = &result->element_class->byval_arg;
1959
1960         mono_class_setup_supertypes (result);
1961
1962         g_hash_table_insert (ptr_hash, sig, result);
1963
1964         mono_loader_unlock ();
1965
1966         return result;
1967 }
1968
1969 MonoClass *
1970 mono_class_from_mono_type (MonoType *type)
1971 {
1972         switch (type->type) {
1973         case MONO_TYPE_OBJECT:
1974                 return type->data.klass? type->data.klass: mono_defaults.object_class;
1975         case MONO_TYPE_VOID:
1976                 return type->data.klass? type->data.klass: mono_defaults.void_class;
1977         case MONO_TYPE_BOOLEAN:
1978                 return type->data.klass? type->data.klass: mono_defaults.boolean_class;
1979         case MONO_TYPE_CHAR:
1980                 return type->data.klass? type->data.klass: mono_defaults.char_class;
1981         case MONO_TYPE_I1:
1982                 return type->data.klass? type->data.klass: mono_defaults.sbyte_class;
1983         case MONO_TYPE_U1:
1984                 return type->data.klass? type->data.klass: mono_defaults.byte_class;
1985         case MONO_TYPE_I2:
1986                 return type->data.klass? type->data.klass: mono_defaults.int16_class;
1987         case MONO_TYPE_U2:
1988                 return type->data.klass? type->data.klass: mono_defaults.uint16_class;
1989         case MONO_TYPE_I4:
1990                 return type->data.klass? type->data.klass: mono_defaults.int32_class;
1991         case MONO_TYPE_U4:
1992                 return type->data.klass? type->data.klass: mono_defaults.uint32_class;
1993         case MONO_TYPE_I:
1994                 return type->data.klass? type->data.klass: mono_defaults.int_class;
1995         case MONO_TYPE_U:
1996                 return type->data.klass? type->data.klass: mono_defaults.uint_class;
1997         case MONO_TYPE_I8:
1998                 return type->data.klass? type->data.klass: mono_defaults.int64_class;
1999         case MONO_TYPE_U8:
2000                 return type->data.klass? type->data.klass: mono_defaults.uint64_class;
2001         case MONO_TYPE_R4:
2002                 return type->data.klass? type->data.klass: mono_defaults.single_class;
2003         case MONO_TYPE_R8:
2004                 return type->data.klass? type->data.klass: mono_defaults.double_class;
2005         case MONO_TYPE_STRING:
2006                 return type->data.klass? type->data.klass: mono_defaults.string_class;
2007         case MONO_TYPE_TYPEDBYREF:
2008                 return type->data.klass? type->data.klass: mono_defaults.typed_reference_class;
2009         case MONO_TYPE_ARRAY:
2010                 return mono_bounded_array_class_get (type->data.array->eklass, type->data.array->rank, TRUE);
2011         case MONO_TYPE_PTR:
2012                 return mono_ptr_class_get (type->data.type);
2013         case MONO_TYPE_FNPTR:
2014                 return mono_fnptr_class_get (type->data.method);
2015         case MONO_TYPE_SZARRAY:
2016                 return mono_array_class_get (type->data.klass, 1);
2017         case MONO_TYPE_CLASS:
2018         case MONO_TYPE_VALUETYPE:
2019                 return type->data.klass;
2020         case MONO_TYPE_GENERICINST:
2021                 g_assert (type->data.generic_inst->klass);
2022                 return type->data.generic_inst->klass;
2023         case MONO_TYPE_VAR:
2024                 return my_mono_class_from_generic_parameter (type->data.generic_param, FALSE);
2025         case MONO_TYPE_MVAR:
2026                 return my_mono_class_from_generic_parameter (type->data.generic_param, TRUE);
2027         default:
2028                 g_warning ("implement me 0x%02x\n", type->type);
2029                 g_assert_not_reached ();
2030         }
2031         
2032         return NULL;
2033 }
2034
2035 /**
2036  * @image: context where the image is created
2037  * @type_spec:  typespec token
2038  */
2039 static MonoClass *
2040 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
2041 {
2042         MonoType *type;
2043         MonoClass *class;
2044
2045         type = mono_type_create_from_typespec (image, type_spec);
2046
2047         switch (type->type) {
2048         case MONO_TYPE_ARRAY:
2049                 class = mono_array_class_get (type->data.array->eklass, type->data.array->rank);
2050                 break;
2051         case MONO_TYPE_SZARRAY:
2052                 class = mono_array_class_get (type->data.klass, 1);
2053                 break;
2054         case MONO_TYPE_PTR:
2055                 class = mono_class_from_mono_type (type->data.type);
2056                 break;
2057         case MONO_TYPE_GENERICINST:
2058                 g_assert (type->data.generic_inst->klass);
2059                 return type->data.generic_inst->klass;
2060                 break;
2061         default:
2062                 /* it seems any type can be stored in TypeSpec as well */
2063                 class = mono_class_from_mono_type (type);
2064                 break;
2065         }
2066
2067         return class;
2068 }
2069
2070 /**
2071  * mono_bounded_array_class_get:
2072  * @element_class: element class 
2073  * @rank: the dimension of the array class
2074  * @bounded: whenever the array has non-zero bounds
2075  *
2076  * Returns: a class object describing the array with element type @element_type and 
2077  * dimension @rank. 
2078  */
2079 MonoClass *
2080 mono_bounded_array_class_get (MonoClass *eclass, guint32 rank, gboolean bounded)
2081 {
2082         MonoImage *image;
2083         MonoClass *class;
2084         MonoClass *parent = NULL;
2085         GSList *list, *rootlist;
2086         int nsize;
2087         char *name;
2088         gboolean corlib_type = FALSE;
2089
2090         g_assert (rank <= 255);
2091
2092         if (rank > 1)
2093                 /* bounded only matters for one-dimensional arrays */
2094                 bounded = FALSE;
2095
2096         image = eclass->image;
2097
2098         mono_loader_lock ();
2099
2100         if ((rootlist = list = g_hash_table_lookup (image->array_cache, eclass))) {
2101                 for (; list; list = list->next) {
2102                         class = list->data;
2103                         if ((class->rank == rank) && (class->byval_arg.type == (bounded ? MONO_TYPE_ARRAY : MONO_TYPE_SZARRAY))) {
2104                                 mono_loader_unlock ();
2105                                 return class;
2106                         }
2107                 }
2108         }
2109
2110         /* for the building corlib use System.Array from it */
2111         if (image->assembly && image->assembly->dynamic && strcmp (image->assembly_name, "mscorlib") == 0) {
2112                 parent = mono_class_from_name (image, "System", "Array");
2113                 corlib_type = TRUE;
2114         } else {
2115                 parent = mono_defaults.array_class;
2116                 if (!parent->inited)
2117                         mono_class_init (parent);
2118         }
2119
2120         class = g_malloc0 (sizeof (MonoClass));
2121
2122         class->image = image;
2123         class->name_space = eclass->name_space;
2124         nsize = strlen (eclass->name);
2125         name = g_malloc (nsize + 2 + rank);
2126         memcpy (name, eclass->name, nsize);
2127         name [nsize] = '[';
2128         if (rank > 1)
2129                 memset (name + nsize + 1, ',', rank - 1);
2130         name [nsize + rank] = ']';
2131         name [nsize + rank + 1] = 0;
2132         class->name = name;
2133         class->type_token = 0;
2134         /* all arrays are marked serializable and sealed, bug #42779 */
2135         class->flags = TYPE_ATTRIBUTE_CLASS | TYPE_ATTRIBUTE_SERIALIZABLE | TYPE_ATTRIBUTE_SEALED |
2136                 (eclass->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK);
2137         class->parent = parent;
2138         class->instance_size = mono_class_instance_size (class->parent);
2139         class->class_size = 0;
2140         mono_class_setup_supertypes (class);
2141
2142         class->rank = rank;
2143         
2144         if (eclass->enumtype)
2145                 class->cast_class = eclass->element_class;
2146         else
2147                 class->cast_class = eclass;
2148
2149         class->element_class = eclass;
2150
2151         if ((rank > 1) || bounded) {
2152                 MonoArrayType *at = g_new0 (MonoArrayType, 1);
2153                 class->byval_arg.type = MONO_TYPE_ARRAY;
2154                 class->byval_arg.data.array = at;
2155                 at->eklass = eclass;
2156                 at->rank = rank;
2157                 /* FIXME: complete.... */
2158         } else {
2159                 class->byval_arg.type = MONO_TYPE_SZARRAY;
2160                 class->byval_arg.data.klass = eclass;
2161         }
2162         class->this_arg = class->byval_arg;
2163         class->this_arg.byref = 1;
2164         if (corlib_type) {
2165                 class->inited = 1;
2166         }
2167
2168         list = g_slist_append (rootlist, class);
2169         g_hash_table_insert (image->array_cache, eclass, list);
2170
2171         mono_loader_unlock ();
2172
2173         return class;
2174 }
2175
2176 /**
2177  * mono_array_class_get:
2178  * @element_class: element class 
2179  * @rank: the dimension of the array class
2180  *
2181  * Returns: a class object describing the array with element type @element_type and 
2182  * dimension @rank. 
2183  */
2184 MonoClass *
2185 mono_array_class_get (MonoClass *eclass, guint32 rank)
2186 {
2187         return mono_bounded_array_class_get (eclass, rank, FALSE);
2188 }
2189
2190 /**
2191  * mono_class_instance_size:
2192  * @klass: a class 
2193  * 
2194  * Returns: the size of an object instance
2195  */
2196 gint32
2197 mono_class_instance_size (MonoClass *klass)
2198 {       
2199         if (!klass->size_inited)
2200                 mono_class_init (klass);
2201
2202         return klass->instance_size;
2203 }
2204
2205 /**
2206  * mono_class_min_align:
2207  * @klass: a class 
2208  * 
2209  * Returns: minimm alignment requirements 
2210  */
2211 gint32
2212 mono_class_min_align (MonoClass *klass)
2213 {       
2214         if (!klass->size_inited)
2215                 mono_class_init (klass);
2216
2217         return klass->min_align;
2218 }
2219
2220 /**
2221  * mono_class_value_size:
2222  * @klass: a class 
2223  *
2224  * This function is used for value types, and return the
2225  * space and the alignment to store that kind of value object.
2226  *
2227  * Returns: the size of a value of kind @klass
2228  */
2229 gint32
2230 mono_class_value_size      (MonoClass *klass, guint32 *align)
2231 {
2232         gint32 size;
2233
2234         /* fixme: check disable, because we still have external revereces to
2235          * mscorlib and Dummy Objects 
2236          */
2237         /*g_assert (klass->valuetype);*/
2238
2239         size = mono_class_instance_size (klass) - sizeof (MonoObject);
2240
2241         if (align)
2242                 *align = klass->min_align;
2243
2244         return size;
2245 }
2246
2247 /**
2248  * mono_class_data_size:
2249  * @klass: a class 
2250  * 
2251  * Returns: the size of the static class data
2252  */
2253 gint32
2254 mono_class_data_size (MonoClass *klass)
2255 {       
2256         if (!klass->inited)
2257                 mono_class_init (klass);
2258
2259         return klass->class_size;
2260 }
2261
2262 /*
2263  * Auxiliary routine to mono_class_get_field
2264  *
2265  * Takes a field index instead of a field token.
2266  */
2267 static MonoClassField *
2268 mono_class_get_field_idx (MonoClass *class, int idx)
2269 {
2270         if (class->field.count){
2271                 if ((idx >= class->field.first) && (idx < class->field.last)){
2272                         return &class->fields [idx - class->field.first];
2273                 }
2274         }
2275
2276         if (!class->parent)
2277                 return NULL;
2278         
2279         return mono_class_get_field_idx (class->parent, idx);
2280 }
2281
2282 /**
2283  * mono_class_get_field:
2284  * @class: the class to lookup the field.
2285  * @field_token: the field token
2286  *
2287  * Returns: A MonoClassField representing the type and offset of
2288  * the field, or a NULL value if the field does not belong to this
2289  * class.
2290  */
2291 MonoClassField *
2292 mono_class_get_field (MonoClass *class, guint32 field_token)
2293 {
2294         int idx = mono_metadata_token_index (field_token);
2295
2296         g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
2297
2298         return mono_class_get_field_idx (class, idx - 1);
2299 }
2300
2301 MonoClassField *
2302 mono_class_get_field_from_name (MonoClass *klass, const char *name)
2303 {
2304         int i;
2305
2306         while (klass) {
2307                 for (i = 0; i < klass->field.count; ++i) {
2308                         if (strcmp (name, klass->fields [i].name) == 0)
2309                                 return &klass->fields [i];
2310                 }
2311                 klass = klass->parent;
2312         }
2313         return NULL;
2314 }
2315
2316 MonoProperty*
2317 mono_class_get_property_from_name (MonoClass *klass, const char *name)
2318 {
2319         int i;
2320
2321         while (klass) {
2322                 for (i = 0; i < klass->property.count; ++i) {
2323                         if (strcmp (name, klass->properties [i].name) == 0)
2324                                 return &klass->properties [i];
2325                 }
2326                 klass = klass->parent;
2327         }
2328         return NULL;
2329 }
2330
2331 /**
2332  * mono_class_get:
2333  * @image: the image where the class resides
2334  * @type_token: the token for the class
2335  * @at: an optional pointer to return the array element type
2336  *
2337  * Returns: the MonoClass that represents @type_token in @image
2338  */
2339 MonoClass *
2340 mono_class_get (MonoImage *image, guint32 type_token)
2341 {
2342         MonoClass *class = NULL;
2343
2344         if (image->dynamic)
2345                 return mono_lookup_dynamic_token (image, type_token);
2346
2347         switch (type_token & 0xff000000){
2348         case MONO_TOKEN_TYPE_DEF:
2349                 class = mono_class_create_from_typedef (image, type_token);
2350                 break;          
2351         case MONO_TOKEN_TYPE_REF:
2352                 class = mono_class_from_typeref (image, type_token);
2353                 break;
2354         case MONO_TOKEN_TYPE_SPEC:
2355                 class = mono_class_create_from_typespec (image, type_token);
2356                 break;
2357         default:
2358                 g_warning ("unknown token type %x", type_token & 0xff000000);
2359                 g_assert_not_reached ();
2360         }
2361
2362         if (!class)
2363                 g_warning ("Could not load class from token 0x%08x in %s", type_token, image->name);
2364
2365         return class;
2366 }
2367
2368 MonoClass *
2369 mono_class_from_name_case (MonoImage *image, const char* name_space, const char *name)
2370 {
2371         MonoTableInfo  *t = &image->tables [MONO_TABLE_TYPEDEF];
2372         guint32 cols [MONO_TYPEDEF_SIZE];
2373         const char *n;
2374         const char *nspace;
2375         guint32 i, visib;
2376
2377         /* add a cache if needed */
2378         for (i = 1; i <= t->rows; ++i) {
2379                 mono_metadata_decode_row (t, i - 1, cols, MONO_TYPEDEF_SIZE);
2380                 /* nested types are accessed from the nesting name */
2381                 visib = cols [MONO_TYPEDEF_FLAGS] & TYPE_ATTRIBUTE_VISIBILITY_MASK;
2382                 if (visib > TYPE_ATTRIBUTE_PUBLIC && visib <= TYPE_ATTRIBUTE_NESTED_ASSEMBLY)
2383                         continue;
2384                 n = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAME]);
2385                 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEDEF_NAMESPACE]);
2386                 if (g_strcasecmp (n, name) == 0 && g_strcasecmp (nspace, name_space) == 0)
2387                         return mono_class_get (image, MONO_TOKEN_TYPE_DEF | i);
2388         }
2389         return NULL;
2390 }
2391
2392 static MonoClass*
2393 return_nested_in (MonoClass *class, char *nested) {
2394         MonoClass *found;
2395         char *s = strchr (nested, '/');
2396         GList *tmp;
2397
2398         if (s) {
2399                 *s = 0;
2400                 s++;
2401         }
2402         for (tmp = class->nested_classes; tmp; tmp = tmp->next) {
2403                 found = tmp->data;
2404                 if (strcmp (found->name, nested) == 0) {
2405                         if (s)
2406                                 return return_nested_in (found, s);
2407                         return found;
2408                 }
2409         }
2410         return NULL;
2411 }
2412
2413 MonoClass *
2414 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
2415 {
2416         GHashTable *nspace_table;
2417         MonoImage *loaded_image;
2418         guint32 token = 0;
2419         MonoClass *class;
2420         char *nested;
2421         char buf [1024];
2422
2423         if ((nested = strchr (name, '/'))) {
2424                 int pos = nested - name;
2425                 int len = strlen (name);
2426                 if (len > 1023)
2427                         return NULL;
2428                 memcpy (buf, name, len + 1);
2429                 buf [pos] = 0;
2430                 nested = buf + pos + 1;
2431                 name = buf;
2432         }
2433
2434         mono_loader_lock ();
2435
2436         nspace_table = g_hash_table_lookup (image->name_cache, name_space);
2437
2438         if (nspace_table)
2439                 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
2440
2441         mono_loader_unlock ();
2442
2443         if (!token)
2444                 return NULL;
2445
2446         if (mono_metadata_token_table (token) == MONO_TABLE_EXPORTEDTYPE) {
2447                 MonoTableInfo  *t = &image->tables [MONO_TABLE_EXPORTEDTYPE];
2448                 guint32 cols [MONO_EXP_TYPE_SIZE];
2449                 guint32 idx, impl;
2450
2451                 idx = mono_metadata_token_index (token);
2452
2453                 mono_metadata_decode_row (t, idx - 1, cols, MONO_EXP_TYPE_SIZE);
2454
2455                 impl = cols [MONO_EXP_TYPE_IMPLEMENTATION];
2456                 if ((impl & IMPLEMENTATION_MASK) == IMPLEMENTATION_FILE) {
2457                         loaded_image = mono_assembly_load_module (image->assembly, impl >> IMPLEMENTATION_BITS);
2458                         if (!loaded_image)
2459                                 return NULL;
2460                         class = mono_class_from_name (loaded_image, name_space, name);
2461                         if (nested)
2462                                 return return_nested_in (class, nested);
2463                         return class;
2464                 } else {
2465                         g_error ("not yet implemented");
2466                 }
2467         }
2468
2469         token = MONO_TOKEN_TYPE_DEF | token;
2470
2471         class = mono_class_get (image, token);
2472         if (nested)
2473                 return return_nested_in (class, nested);
2474         return class;
2475 }
2476
2477 gboolean
2478 mono_class_is_subclass_of (MonoClass *klass, MonoClass *klassc, 
2479                            gboolean check_interfaces)
2480 {
2481  again:
2482         if (check_interfaces && (klassc->flags & TYPE_ATTRIBUTE_INTERFACE) && !(klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
2483                 if ((klassc->interface_id <= klass->max_interface_id) &&
2484                         (klass->interface_offsets [klassc->interface_id] >= 0))
2485                         return TRUE;
2486         } else if (check_interfaces && (klassc->flags & TYPE_ATTRIBUTE_INTERFACE) && (klass->flags & TYPE_ATTRIBUTE_INTERFACE)) {
2487                 int i;
2488
2489                 for (i = 0; i < klass->interface_count; i ++) {
2490                         MonoClass *ic =  klass->interfaces [i];
2491                         if (ic == klassc)
2492                                 return TRUE;
2493                 }
2494         } else {
2495                 if (!(klass->flags & TYPE_ATTRIBUTE_INTERFACE) && mono_class_has_parent (klass, klassc))
2496                         return TRUE;
2497                 if (klass->generic_inst) {
2498                         MonoType *parent = klass->generic_inst->parent;
2499                         if (!parent)
2500                                 return FALSE;
2501
2502                         if (mono_metadata_type_equal (parent, &klassc->byval_arg))
2503                                 return TRUE;
2504                         klass = mono_class_from_mono_type (parent);
2505                         goto again;
2506                 }
2507         }
2508
2509         /* 
2510          * MS.NET thinks interfaces are a subclass of Object, so we think it as
2511          * well.
2512          */
2513         if (klassc == mono_defaults.object_class)
2514                 return TRUE;
2515         
2516         return FALSE;
2517 }
2518
2519 gboolean
2520 mono_class_is_assignable_from (MonoClass *klass, MonoClass *oklass)
2521 {
2522         if (!klass->inited)
2523                 mono_class_init (klass);
2524
2525         if (!oklass->inited)
2526                 mono_class_init (oklass);
2527
2528         if (klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
2529                 if ((klass->interface_id <= oklass->max_interface_id) &&
2530                     (oklass->interface_offsets [klass->interface_id] != -1))
2531                         return TRUE;
2532         } else
2533                 if (klass->rank) {
2534                         MonoClass *eclass, *eoclass;
2535
2536                         if (oklass->rank != klass->rank)
2537                                 return FALSE;
2538
2539                         /* vectors vs. one dimensional arrays */
2540                         if (oklass->byval_arg.type != klass->byval_arg.type)
2541                                 return FALSE;
2542
2543                         eclass = klass->cast_class;
2544                         eoclass = oklass->cast_class;
2545
2546
2547                         /* 
2548                          * a is b does not imply a[] is b[] when a is a valuetype, and
2549                          * b is a reference type.
2550                          */
2551
2552                         if (eoclass->valuetype) {
2553                                 if ((eclass == mono_defaults.enum_class) || 
2554                                         (eclass == mono_defaults.enum_class->parent) ||
2555                                         (eclass == mono_defaults.object_class))
2556                                         return FALSE;
2557                         }
2558
2559                         return mono_class_is_assignable_from (klass->cast_class, oklass->cast_class);
2560                 }
2561         else
2562                 if (klass == mono_defaults.object_class)
2563                         return TRUE;
2564
2565         return mono_class_has_parent (oklass, klass);
2566 }       
2567
2568 /*
2569  * mono_class_needs_cctor_run:
2570  *
2571  *  Determines whenever the class has a static constructor and whenever it
2572  * needs to be called when executing CALLER.
2573  */
2574 gboolean
2575 mono_class_needs_cctor_run (MonoClass *klass, MonoMethod *caller)
2576 {
2577         int i;
2578         MonoMethod *method;
2579         
2580         for (i = 0; i < klass->method.count; ++i) {
2581                 method = klass->methods [i];
2582                 if ((method->flags & METHOD_ATTRIBUTE_SPECIAL_NAME) && 
2583                     (strcmp (".cctor", method->name) == 0)) {
2584                         if (caller == method)
2585                                 return FALSE;
2586                         return TRUE;
2587                 }
2588         }
2589         return FALSE;
2590 }
2591
2592 /*
2593  * Returns the nnumber of bytes an element of type klass
2594  * uses when stored into an array.
2595  */
2596 gint32
2597 mono_class_array_element_size (MonoClass *klass)
2598 {
2599         int t = klass->byval_arg.type;
2600         
2601 handle_enum:
2602         switch (t) {
2603         case MONO_TYPE_I1:
2604         case MONO_TYPE_U1:
2605         case MONO_TYPE_BOOLEAN:
2606                 return 1;
2607         case MONO_TYPE_I2:
2608         case MONO_TYPE_U2:
2609         case MONO_TYPE_CHAR:
2610                 return 2;
2611         case MONO_TYPE_I4:
2612         case MONO_TYPE_U4:
2613         case MONO_TYPE_R4:
2614                 return 4;
2615         case MONO_TYPE_I:
2616         case MONO_TYPE_U:
2617         case MONO_TYPE_PTR:
2618         case MONO_TYPE_CLASS:
2619         case MONO_TYPE_STRING:
2620         case MONO_TYPE_OBJECT:
2621         case MONO_TYPE_SZARRAY:
2622         case MONO_TYPE_ARRAY: 
2623         case MONO_TYPE_VAR:
2624         case MONO_TYPE_MVAR:   
2625                 return sizeof (gpointer);
2626         case MONO_TYPE_I8:
2627         case MONO_TYPE_U8:
2628         case MONO_TYPE_R8:
2629                 return 8;
2630         case MONO_TYPE_VALUETYPE:
2631                 if (klass->enumtype) {
2632                         t = klass->enum_basetype->type;
2633                         goto handle_enum;
2634                 }
2635                 return mono_class_instance_size (klass) - sizeof (MonoObject);
2636         default:
2637                 g_error ("unknown type 0x%02x in mono_class_array_element_size", t);
2638         }
2639         return -1;
2640 }
2641
2642 /**
2643  * mono_array_element_size:
2644  * @ac: pointer to a #MonoArrayClass
2645  *
2646  * Returns: the size of single array element.
2647  */
2648 gint32
2649 mono_array_element_size (MonoClass *ac)
2650 {
2651         return mono_class_array_element_size (ac->element_class);
2652 }
2653
2654 gpointer
2655 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
2656 {
2657         if (image->dynamic) {
2658                 gpointer obj = mono_lookup_dynamic_token (image, token);
2659
2660                 switch (token & 0xff000000) {
2661                 case MONO_TOKEN_TYPE_DEF:
2662                 case MONO_TOKEN_TYPE_REF:
2663                 case MONO_TOKEN_TYPE_SPEC:
2664                         if (handle_class)
2665                                 *handle_class = mono_defaults.typehandle_class;
2666                         return &((MonoClass*)obj)->byval_arg;
2667                 case MONO_TOKEN_METHOD_DEF:
2668                         if (handle_class)
2669                                 *handle_class = mono_defaults.methodhandle_class;
2670                         return obj;
2671                 case MONO_TOKEN_FIELD_DEF:
2672                         if (handle_class)
2673                                 *handle_class = mono_defaults.fieldhandle_class;
2674                         return obj;
2675                 default:
2676                         g_assert_not_reached ();
2677                 }
2678         }
2679
2680         switch (token & 0xff000000) {
2681         case MONO_TOKEN_TYPE_DEF:
2682         case MONO_TOKEN_TYPE_REF: {
2683                 MonoClass *class;
2684                 if (handle_class)
2685                         *handle_class = mono_defaults.typehandle_class;
2686                 class = mono_class_get (image, token);
2687                 mono_class_init (class);
2688                 /* We return a MonoType* as handle */
2689                 return &class->byval_arg;
2690         }
2691         case MONO_TOKEN_TYPE_SPEC: {
2692                 MonoClass *class;
2693                 if (handle_class)
2694                         *handle_class = mono_defaults.typehandle_class;
2695                 class = mono_class_create_from_typespec (image, token);
2696                 mono_class_init (class);
2697                 return &class->byval_arg;
2698         }
2699         case MONO_TOKEN_FIELD_DEF: {
2700                 MonoClass *class;
2701                 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
2702                 class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
2703                 mono_class_init (class);
2704                 if (handle_class)
2705                         *handle_class = mono_defaults.fieldhandle_class;
2706                 return mono_class_get_field (class, token);
2707         }
2708         case MONO_TOKEN_METHOD_DEF: {
2709                 MonoMethod *meth;
2710                 meth = mono_get_method (image, token, NULL);
2711                 if (handle_class)
2712                         *handle_class = mono_defaults.methodhandle_class;
2713                 return meth;
2714         }
2715         case MONO_TOKEN_MEMBER_REF: {
2716                 guint32 cols [MONO_MEMBERREF_SIZE];
2717                 const char *sig;
2718                 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
2719                 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
2720                 mono_metadata_decode_blob_size (sig, &sig);
2721                 if (*sig == 0x6) { /* it's a field */
2722                         MonoClass *klass;
2723                         MonoClassField *field;
2724                         field = mono_field_from_token (image, token, &klass);
2725                         if (handle_class)
2726                                 *handle_class = mono_defaults.fieldhandle_class;
2727                         return field;
2728                 } else {
2729                         MonoMethod *meth;
2730                         meth = mono_get_method (image, token, NULL);
2731                         if (handle_class)
2732                                 *handle_class = mono_defaults.methodhandle_class;
2733                         return meth;
2734                 }
2735         }
2736         default:
2737                 g_warning ("Unknown token 0x%08x in ldtoken", token);
2738                 break;
2739         }
2740         return NULL;
2741 }
2742
2743 /**
2744  * This function might need to call runtime functions so it can't be part
2745  * of the metadata library.
2746  */
2747 static MonoLookupDynamicToken lookup_dynamic = NULL;
2748
2749 void
2750 mono_install_lookup_dynamic_token (MonoLookupDynamicToken func)
2751 {
2752         lookup_dynamic = func;
2753 }
2754
2755 gpointer
2756 mono_lookup_dynamic_token (MonoImage *image, guint32 token)
2757 {
2758         return lookup_dynamic (image, token);
2759 }
2760
2761
2762