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