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