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