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