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