2 * class.c: Class management for the Mono runtime
5 * Miguel de Icaza (miguel@ximian.com)
7 * (C) 2001 Ximian, Inc.
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.
22 #include <mono/metadata/image.h>
23 #include <mono/metadata/cil-coff.h>
24 #include <mono/metadata/metadata.h>
25 #include <mono/metadata/tabledefs.h>
26 #include <mono/metadata/tokentype.h>
27 #include <mono/metadata/class.h>
28 #include <mono/metadata/object.h>
29 #include <mono/metadata/appdomain.h>
30 #include <mono/metadata/mono-endian.h>
32 #define CSIZE(x) (sizeof (x) / 4)
34 gboolean mono_print_vtable = FALSE;
36 static MonoClass * mono_class_create_from_typedef (MonoImage *image, guint32 type_token);
39 default_trampoline (MonoMethod *method)
45 default_runtime_class_init (MonoClass *klass)
50 static MonoTrampoline arch_create_jit_trampoline = default_trampoline;
51 static MonoRuntimeClassInit mono_runtime_class_init = default_runtime_class_init;
54 mono_install_trampoline (MonoTrampoline func)
56 arch_create_jit_trampoline = func? func: default_trampoline;
60 mono_install_runtime_class_init (MonoRuntimeClassInit func)
62 mono_runtime_class_init = func? func: default_runtime_class_init;
66 mono_class_create_from_typeref (MonoImage *image, guint32 type_token)
68 guint32 cols [MONO_TYPEREF_SIZE];
69 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
71 const char *name, *nspace;
74 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
75 g_assert ((cols [MONO_TYPEREF_SCOPE] & 0x3) == 2);
76 idx = cols [MONO_TYPEREF_SCOPE] >> 2;
78 if (!image->references || !image->references [idx-1]) {
80 * detected a reference to mscorlib, we simply return a reference to a dummy
81 * until we have a better solution.
83 fprintf(stderr, "Sending dummy where %s.%s expected\n", mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]), mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]));
85 res = mono_class_from_name (image, "System", "MonoDummy");
86 /* prevent method loading */
88 /* some storage if the type is used - very ugly hack */
89 res->instance_size = 2*sizeof (gpointer);
93 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
94 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
96 /* load referenced assembly */
97 image = image->references [idx-1]->image;
99 return mono_class_from_name (image, nspace, name);
103 * class_compute_field_layout:
104 * @m: pointer to the metadata.
105 * @class: The class to initialize
107 * Initializes the class->fields.
109 * Currently we only support AUTO_LAYOUT, and do not even try to do
110 * a good job at it. This is temporary to get the code for Paolo.
113 class_compute_field_layout (MonoClass *class)
115 MonoImage *m = class->image;
116 const int top = class->field.count;
117 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
118 MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
122 * Fetch all the field information.
124 for (i = 0; i < top; i++){
126 guint32 cols [MONO_FIELD_SIZE];
127 int idx = class->field.first + i;
129 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
130 /* The name is needed for fieldrefs */
131 class->fields [i].name = mono_metadata_string_heap (m, cols [MONO_FIELD_NAME]);
132 sig = mono_metadata_blob_heap (m, cols [MONO_FIELD_SIGNATURE]);
133 mono_metadata_decode_value (sig, &sig);
134 /* FIELD signature == 0x06 */
135 g_assert (*sig == 0x06);
136 class->fields [i].type = mono_metadata_parse_field_type (
137 m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
138 if (cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_HAS_FIELD_RVA) {
139 mono_metadata_field_info (m, idx, NULL, &class->fields [i].data, NULL);
140 if (!class->fields [i].data)
141 g_warning ("field %s in %s should have RVA data, but hasn't", class->fields [i].name, class->name);
143 if (class->enumtype && !(cols [MONO_FIELD_FLAGS] & FIELD_ATTRIBUTE_STATIC)) {
144 class->enum_basetype = class->fields [i].type;
145 class->element_class = mono_class_from_mono_type (class->enum_basetype);
148 if (class->enumtype && !class->enum_basetype) {
149 if (!((strcmp (class->name, "Enum") == 0) && (strcmp (class->name_space, "System") == 0)))
153 * Compute field layout and total size.
156 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
157 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
158 for (i = 0; i < top; i++){
161 size = mono_type_size (class->fields [i].type, &align);
162 if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
163 class->fields [i].offset = class->class_size;
164 class->fields [i].offset += align - 1;
165 class->fields [i].offset &= ~(align - 1);
166 class->class_size = class->fields [i].offset + size;
168 class->min_align = MAX (align, class->min_align);
169 class->fields [i].offset = class->instance_size;
170 class->fields [i].offset += align - 1;
171 class->fields [i].offset &= ~(align - 1);
172 class->instance_size = class->fields [i].offset + size;
175 if (class->instance_size & (class->min_align - 1)) {
176 class->instance_size += class->min_align - 1;
177 class->instance_size &= ~(class->min_align - 1);
180 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
181 for (i = 0; i < top; i++){
183 int idx = class->field.first + i;
186 * There must be info about all the fields in a type if it
187 * uses explicit layout.
190 size = mono_type_size (class->fields [i].type, &align);
191 if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
192 class->fields [i].offset = class->class_size;
193 class->fields [i].offset += align - 1;
194 class->fields [i].offset &= ~(align - 1);
195 class->class_size = class->fields [i].offset + size;
197 mono_metadata_field_info (m, idx, &class->fields [i].offset, NULL, NULL);
198 if (class->fields [i].offset == (guint32)-1)
199 g_warning ("%s not initialized correctly (missing field layout info for %s)", class->name, class->fields [i].name);
201 * The offset is from the start of the object: this works for both
202 * classes and valuetypes.
204 class->fields [i].offset += sizeof (MonoObject);
208 size += class->fields [i].offset;
209 class->instance_size = MAX (class->instance_size, size);
217 init_properties (MonoClass *class)
219 guint startm, endm, i, j;
220 guint32 cols [MONO_PROPERTY_SIZE];
221 MonoTableInfo *pt = &class->image->tables [MONO_TABLE_PROPERTY];
222 MonoTableInfo *msemt = &class->image->tables [MONO_TABLE_METHODSEMANTICS];
224 class->property.first = mono_metadata_properties_from_typedef (class->image, mono_metadata_token_index (class->type_token) - 1, &class->property.last);
225 class->property.count = class->property.last - class->property.first;
227 class->properties = g_new0 (MonoProperty, class->property.count);
228 for (i = class->property.first; i < class->property.last; ++i) {
229 mono_metadata_decode_row (pt, i, cols, MONO_PROPERTY_SIZE);
230 class->properties [i - class->property.first].attrs = cols [MONO_PROPERTY_FLAGS];
231 class->properties [i - class->property.first].name = mono_metadata_string_heap (class->image, cols [MONO_PROPERTY_NAME]);
233 startm = mono_metadata_methods_from_property (class->image, i, &endm);
234 for (j = startm; j < endm; ++j) {
235 mono_metadata_decode_row (msemt, j, cols, MONO_METHOD_SEMA_SIZE);
236 switch (cols [MONO_METHOD_SEMA_SEMANTICS]) {
238 class->properties [i - class->property.first].set = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
241 class->properties [i - class->property.first].get = class->methods [cols [MONO_METHOD_SEMA_METHOD] - 1 - class->method.first];
251 mono_get_unique_iid (MonoClass *class)
253 static GHashTable *iid_hash = NULL;
254 static guint iid = 0;
259 g_assert (class->flags & TYPE_ATTRIBUTE_INTERFACE);
262 iid_hash = g_hash_table_new (g_str_hash, g_str_equal);
264 str = g_strdup_printf ("%s|%s.%s\n", class->image->name, class->name_space, class->name);
266 if (g_hash_table_lookup_extended (iid_hash, str, NULL, &value)) {
270 g_hash_table_insert (iid_hash, str, (gpointer)iid);
280 * @class: the class to initialize
282 * compute the instance_size, class_size and other infos that cannot be
283 * computed at mono_class_get() time. Also compute a generic vtable and
284 * the method slot numbers. We use this infos later to create a domain
288 mono_class_init (MonoClass *class)
291 MonoMethod **vtable = class->vtable;
292 int i, max_iid, cur_slot = 0;
301 if (!class->parent->inited)
302 mono_class_init (class->parent);
303 class->instance_size += class->parent->instance_size;
304 class->class_size += class->parent->class_size;
305 class->min_align = class->parent->min_align;
306 cur_slot = class->parent->vtable_size;
308 class->min_align = 1;
311 * Computes the size used by the fields, and their locations
313 if (class->field.count > 0){
314 class->fields = g_new0 (MonoClassField, class->field.count);
315 class_compute_field_layout (class);
318 /* initialize method pointers */
319 class->methods = g_new (MonoMethod*, class->method.count);
320 for (i = 0; i < class->method.count; ++i)
321 class->methods [i] = mono_get_method (class->image,
322 MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
324 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
325 for (i = 0; i < class->method.count; ++i)
326 class->methods [i]->slot = i;
330 //printf ("METAINIT %s.%s\n", class->name_space, class->name);
332 /* compute maximum number of slots and maximum interface id */
334 for (k = class; k ; k = k->parent) {
335 for (i = 0; i < k->interface_count; i++) {
336 ic = k->interfaces [i];
339 mono_class_init (ic);
341 if (max_iid < ic->interface_id)
342 max_iid = ic->interface_id;
346 class->max_interface_id = max_iid;
347 /* compute vtable offset for interfaces */
348 class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
350 for (i = 0; i <= max_iid; i++)
351 class->interface_offsets [i] = -1;
353 for (i = 0; i < class->interface_count; i++) {
354 ic = class->interfaces [i];
355 class->interface_offsets [ic->interface_id] = cur_slot;
356 cur_slot += ic->method.count;
359 for (k = class->parent; k ; k = k->parent) {
360 for (i = 0; i < k->interface_count; i++) {
361 ic = k->interfaces [i];
362 if (class->interface_offsets [ic->interface_id] == -1) {
363 int io = k->interface_offsets [ic->interface_id];
366 g_assert (io <= class->vtable_size);
368 class->interface_offsets [ic->interface_id] = io;
373 if (class->parent && class->parent->vtable_size)
374 memcpy (class->vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
376 for (k = class; k ; k = k->parent) {
377 for (i = 0; i < k->interface_count; i++) {
380 ic = k->interfaces [i];
381 io = k->interface_offsets [ic->interface_id];
384 g_assert (io <= class->vtable_size);
387 for (l = 0; l < ic->method.count; l++) {
388 MonoMethod *im = ic->methods [l];
389 for (j = 0; j < class->method.count; ++j) {
390 MonoMethod *cm = class->methods [j];
391 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
392 !(cm->flags & METHOD_ATTRIBUTE_PUBLIC) ||
393 !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
395 if (!strcmp(cm->name, im->name) &&
396 mono_metadata_signature_equal (cm->signature, im->signature)) {
397 g_assert (io + l <= class->vtable_size);
398 vtable [io + l] = cm;
403 /* already implemented */
404 if (io >= k->vtable_size)
408 for (l = 0; l < ic->method.count; l++) {
409 MonoMethod *im = ic->methods [l];
412 g_assert (io + l <= class->vtable_size);
417 for (k1 = class; k1; k1 = k1->parent) {
418 for (j = 0; j < k1->method.count; ++j) {
419 MonoMethod *cm = k1->methods [j];
421 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
422 !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
425 if (!strcmp(cm->name, im->name) &&
426 mono_metadata_signature_equal (cm->signature, im->signature)) {
427 g_assert (io + l <= class->vtable_size);
428 vtable [io + l] = cm;
433 g_assert (io + l <= class->vtable_size);
439 for (l = 0; l < ic->method.count; l++) {
440 MonoMethod *im = ic->methods [l];
442 if (ic->name_space && ic->name_space [0])
443 qname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
445 qname = g_strconcat (ic->name, ".", im->name, NULL);
447 for (j = 0; j < class->method.count; ++j) {
448 MonoMethod *cm = class->methods [j];
450 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
453 if (!strcmp (cm->name, qname) &&
454 mono_metadata_signature_equal (cm->signature, im->signature)) {
455 g_assert (io + l <= class->vtable_size);
456 vtable [io + l] = cm;
464 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
465 for (l = 0; l < ic->method.count; l++) {
466 MonoMethod *im = ic->methods [l];
467 g_assert (io + l <= class->vtable_size);
468 if (!(vtable [io + l])) {
469 printf ("no implementation for interface method %s.%s::%s in class %s.%s\n",
470 ic->name_space, ic->name, im->name, class->name_space, class->name);
472 for (j = 0; j < class->method.count; ++j) {
473 MonoMethod *cm = class->methods [j];
475 printf ("METHOD %s\n", cm->name);
477 g_assert_not_reached ();
482 for (l = 0; l < ic->method.count; l++) {
483 MonoMethod *im = vtable [io + l];
486 g_assert (io + l <= class->vtable_size);
488 // fixme: why do we need this ?
490 // g_assert_not_reached ();
497 for (i = 0; i < class->method.count; ++i) {
500 cm = class->methods [i];
502 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
506 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
507 for (k = class->parent; k ; k = k->parent) {
509 for (j = 0; j < k->method.count; ++j) {
510 MonoMethod *m1 = k->methods [j];
511 if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
513 if (!strcmp(cm->name, m1->name) &&
514 mono_metadata_signature_equal (cm->signature, m1->signature)) {
515 cm->slot = k->methods [j]->slot;
516 g_assert (cm->slot < class->vtable_size);
526 cm->slot = cur_slot++;
528 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
529 vtable [cm->slot] = cm;
532 init_properties (class);
534 i = mono_metadata_nesting_typedef (class->image, class->type_token);
537 guint32 cols [MONO_NESTED_CLASS_SIZE];
538 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_NESTEDCLASS], i - 1, cols, MONO_NESTED_CLASS_SIZE);
539 if (cols [MONO_NESTED_CLASS_ENCLOSING] != mono_metadata_token_index (class->type_token))
541 nclass = mono_class_create_from_typedef (class->image, MONO_TOKEN_TYPE_DEF | cols [MONO_NESTED_CLASS_NESTED]);
542 class->nested_classes = g_list_prepend (class->nested_classes, nclass);
546 if (mono_print_vtable) {
549 for (i = 0; i <= max_iid; i++)
550 if (class->interface_offsets [i] != -1)
553 printf ("VTable %s.%s (size = %d, interfaces = %d)\n", class->name_space,
554 class->name, class->vtable_size, icount);
556 for (i = 0; i < class->vtable_size; ++i) {
561 printf (" slot %03d(%03d) %s.%s:%s\n", i, cm->slot,
562 cm->klass->name_space, cm->klass->name,
569 printf ("Interfaces %s.%s (max_iid = %d)\n", class->name_space,
570 class->name, max_iid);
572 for (i = 0; i < class->interface_count; i++) {
573 ic = class->interfaces [i];
574 printf (" slot %03d(%03d) %s.%s\n",
575 class->interface_offsets [ic->interface_id],
576 ic->method.count, ic->name_space, ic->name);
579 for (k = class->parent; k ; k = k->parent) {
580 for (i = 0; i < k->interface_count; i++) {
581 ic = k->interfaces [i];
582 printf (" slot %03d(%03d) %s.%s\n",
583 class->interface_offsets [ic->interface_id],
584 ic->method.count, ic->name_space, ic->name);
593 * @domain: the application domain
594 * @class: the class to initialize
596 * VTables are domain specific because we create domain specific code, and
597 * they contain the domain specific static class data.
600 mono_class_vtable (MonoDomain *domain, MonoClass *class)
604 MonoClassField *field;
606 guint32 cols [MONO_CONSTANT_SIZE];
613 /* can interfaces have static fields? */
614 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
615 g_assert_not_reached ();
617 if ((vt = g_hash_table_lookup (domain->class_vtable_hash, class)))
621 mono_class_init (class);
623 vt = g_malloc0 (sizeof (MonoVTable) + class->vtable_size * sizeof (gpointer));
627 if (class->class_size) {
628 vt->data = g_malloc0 (class->class_size + 8);
629 /* align: fixme not 64 bit clean */
630 if (((guint32)vt->data) & 0x7)
631 vt->data += 8 - (((guint32)vt->data) & 0x7);
634 for (i = class->field.first; i < class->field.last; ++i) {
635 field = &class->fields [i - class->field.first];
636 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
638 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
640 cindex = mono_metadata_get_constant_index (class->image, MONO_TOKEN_FIELD_DEF | (i + 1));
642 g_warning ("constant for field %s not found", field->name);
645 mono_metadata_decode_row (&class->image->tables [MONO_TABLE_CONSTANT], cindex - 1, cols, MONO_CONSTANT_SIZE);
646 p = mono_metadata_blob_heap (class->image, cols [MONO_CONSTANT_VALUE]);
647 mono_metadata_decode_blob_size (p, &p);
648 t = (char*)vt->data + field->offset;
649 /* should we check that the type matches? */
650 switch (cols [MONO_CONSTANT_TYPE]) {
651 case MONO_TYPE_BOOLEAN:
659 guint16 *val = (guint16*)t;
665 guint32 *val = (guint32*)t;
671 guint64 *val = (guint64*)t;
676 float *val = (float*)t;
681 double *val = (double*)t;
685 case MONO_TYPE_STRING: {
686 g_warning ("we don't handle strings in constant table");
689 case MONO_TYPE_CLASS:
690 /* nothing to do, we malloc0 the data and the value can be 0 only */
693 g_warning ("type 0x%02x should not be in constant table", cols [MONO_CONSTANT_TYPE]);
697 vt->interface_offsets = g_malloc0 (sizeof (gpointer) * (class->max_interface_id + 1));
699 /* initialize interface offsets */
700 for (k = class; k ; k = k->parent) {
701 for (i = 0; i < k->interface_count; i++) {
703 MonoClass *ic = k->interfaces [i];
704 slot = class->interface_offsets [ic->interface_id];
705 vt->interface_offsets [ic->interface_id] = &vt->vtable [slot];
709 /* initialize vtable */
710 for (i = 0; i < class->vtable_size; ++i) {
713 if ((cm = class->vtable [i]))
714 vt->vtable [i] = arch_create_jit_trampoline (cm);
717 g_hash_table_insert (domain->class_vtable_hash, class, vt);
719 mono_runtime_class_init (class);
725 * Compute a relative numbering of the class hierarchy as described in
726 * "Java for Large-Scale Scientific Computations?"
729 mono_compute_relative_numbering (MonoClass *class, int *c)
737 for (s = class->subclasses; s; s = s->next)
738 mono_compute_relative_numbering ((MonoClass *)s->data, c);
740 class->diffval = *c - class->baseval;
744 * @image: context where the image is created
745 * @type_token: typedef token
748 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
750 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
751 MonoClass *class, *parent = NULL;
752 guint32 cols [MONO_TYPEDEF_SIZE];
753 guint32 cols_next [MONO_TYPEDEF_SIZE];
754 guint tidx = mono_metadata_token_index (type_token);
755 const char *name, *nspace;
756 guint vtsize = 0, icount = 0;
757 MonoClass **interfaces;
760 if ((class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
763 g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
765 mono_metadata_decode_row (tt, tidx - 1, cols, CSIZE (cols));
767 if (tt->rows > tidx) {
768 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
769 vtsize += cols_next [MONO_TYPEDEF_METHOD_LIST] - cols [MONO_TYPEDEF_METHOD_LIST];
771 vtsize += image->tables [MONO_TABLE_METHOD].rows - cols [MONO_TYPEDEF_METHOD_LIST] + 1;
774 name = mono_metadata_string_heap (image, cols[1]);
775 nspace = mono_metadata_string_heap (image, cols[2]);
777 if (!(!strcmp (nspace, "System") && !strcmp (name, "Object")) &&
778 !(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
779 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [3]));
781 interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
783 for (i = 0; i < icount; i++)
784 vtsize += interfaces [i]->method.count;
787 vtsize += parent->vtable_size;
789 if (cols [0] & TYPE_ATTRIBUTE_INTERFACE)
792 class = g_malloc0 (sizeof (MonoClass) + vtsize * sizeof (gpointer));
794 g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
796 class->parent = parent;
797 class->interfaces = interfaces;
798 class->interface_count = icount;
799 class->vtable_size = vtsize;
801 class->this_arg.byref = 1;
802 class->this_arg.data.klass = class;
803 class->this_arg.type = MONO_TYPE_CLASS;
804 class->byval_arg.data.klass = class;
805 class->byval_arg.type = MONO_TYPE_CLASS;
808 class->name_space = nspace;
810 class->image = image;
811 class->type_token = type_token;
812 class->flags = cols [0];
814 class->element_class = class;
816 /*g_print ("Init class %s\n", name);*/
818 /* if root of the hierarchy */
819 if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
820 class->parent = NULL;
821 class->instance_size = sizeof (MonoObject);
822 } else if (!(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
824 class->parent = mono_class_get (image, mono_metadata_token_from_dor (cols [3]));
825 if (class->parent->enumtype || ((strcmp (class->parent->name, "ValueType") == 0) && (strcmp (class->parent->name_space, "System") == 0)))
826 class->valuetype = 1;
827 if (((strcmp (class->parent->name, "Enum") == 0) && (strcmp (class->parent->name_space, "System") == 0))) {
828 class->valuetype = class->enumtype = 1;
830 //class->enumtype = class->parent->enumtype;
831 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
832 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
835 if (!strcmp (nspace, "System")) {
836 if (!strcmp (name, "ValueType")) {
838 * do not set the valuetype bit for System.ValueType.
839 * class->valuetype = 1;
841 } else if (!strcmp (name, "Enum")) {
843 * do not set the valuetype bit for System.Enum.
844 * class->valuetype = 1;
846 class->valuetype = 0;
848 } else if (!strcmp (name, "Object")) {
849 class->this_arg.type = class->byval_arg.type = MONO_TYPE_OBJECT;
850 } else if (!strcmp (name, "String")) {
851 class->this_arg.type = class->byval_arg.type = MONO_TYPE_STRING;
855 if (class->valuetype) {
856 int t = MONO_TYPE_VALUETYPE;
857 if (!strcmp (nspace, "System")) {
860 if (!strcmp (name, "Boolean")) {
861 t = MONO_TYPE_BOOLEAN;
862 } else if (!strcmp(name, "Byte")) {
867 if (!strcmp (name, "Char")) {
872 if (!strcmp (name, "Double")) {
877 if (!strcmp (name, "Int32")) {
879 } else if (!strcmp(name, "Int16")) {
881 } else if (!strcmp(name, "Int64")) {
883 } else if (!strcmp(name, "IntPtr")) {
888 if (!strcmp (name, "Single")) {
890 } else if (!strcmp(name, "SByte")) {
895 if (!strcmp (name, "UInt32")) {
897 } else if (!strcmp(name, "UInt16")) {
899 } else if (!strcmp(name, "UInt64")) {
901 } else if (!strcmp(name, "UIntPtr")) {
906 if (!strcmp (name, "Void")) {
914 class->this_arg.type = class->byval_arg.type = t;
918 * Compute the field and method lists
920 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
921 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
923 if (tt->rows > tidx){
924 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
925 class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
926 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
928 class->field.last = image->tables [MONO_TABLE_FIELD].rows;
929 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
932 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
933 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
934 class->field.count = class->field.last - class->field.first;
936 class->field.count = 0;
938 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
939 class->method.count = class->method.last - class->method.first;
941 class->method.count = 0;
943 /* reserve space to store vector pointer in arrays */
944 if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
945 class->instance_size += 2 * sizeof (gpointer);
946 g_assert (class->field.count == 0);
949 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
950 class->interface_id = mono_get_unique_iid (class);
952 //class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count);
955 mono_class_init (class);
957 if ((type_token = mono_metadata_nested_in_typedef (image, type_token)))
958 class->nested_in = mono_class_create_from_typedef (image, type_token);
963 mono_create_ptr_class (MonoType *type)
967 static GHashTable *ptr_hash = NULL;
970 ptr_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
971 el_class = mono_class_from_mono_type (type);
972 if ((result = g_hash_table_lookup (ptr_hash, el_class)))
974 result = g_new0 (MonoClass, 1);
976 result->parent = NULL; /* no parent for PTR types */
977 result->name = "System";
978 result->name_space = "MonoPtrFakeClass";
979 result->image = NULL;
980 result->inited = TRUE;
981 /* Can pointers get boxed? */
982 result->instance_size = sizeof (gpointer);
984 * baseval, diffval: need them to allow casting ?
986 result->element_class = el_class;
987 result->enum_basetype = &result->element_class->byval_arg;
989 result->this_arg.type = result->byval_arg.type = MONO_TYPE_PTR;
990 result->this_arg.data.type = result->byval_arg.data.type = result->enum_basetype;
991 result->this_arg.byref = TRUE;
993 g_hash_table_insert (ptr_hash, el_class, result);
999 mono_class_from_mono_type (MonoType *type)
1001 switch (type->type) {
1002 case MONO_TYPE_OBJECT:
1003 return mono_defaults.object_class;
1004 case MONO_TYPE_VOID:
1005 return mono_defaults.void_class;
1006 case MONO_TYPE_BOOLEAN:
1007 return mono_defaults.boolean_class;
1008 case MONO_TYPE_CHAR:
1009 return mono_defaults.char_class;
1011 return mono_defaults.sbyte_class;
1013 return mono_defaults.byte_class;
1015 return mono_defaults.int16_class;
1017 return mono_defaults.uint16_class;
1019 return mono_defaults.int32_class;
1021 return mono_defaults.uint32_class;
1023 return mono_defaults.int_class;
1025 return mono_defaults.uint_class;
1027 return mono_defaults.int64_class;
1029 return mono_defaults.uint64_class;
1031 return mono_defaults.single_class;
1033 return mono_defaults.double_class;
1034 case MONO_TYPE_STRING:
1035 return mono_defaults.string_class;
1036 case MONO_TYPE_ARRAY:
1037 return mono_array_class_get (mono_class_from_mono_type (type->data.array->type), type->data.array->rank);
1039 return mono_create_ptr_class (type->data.type);
1040 case MONO_TYPE_SZARRAY:
1041 return mono_array_class_get (mono_class_from_mono_type (type->data.type), 1);
1042 case MONO_TYPE_CLASS:
1043 case MONO_TYPE_VALUETYPE:
1044 return type->data.klass;
1046 g_warning ("implement me %02x\n", type->type);
1047 g_assert_not_reached ();
1054 * @image: context where the image is created
1055 * @type_spec: typespec token
1058 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
1061 MonoClass *class, *eclass;
1063 type = mono_type_create_from_typespec (image, type_spec);
1065 switch (type->type) {
1066 case MONO_TYPE_ARRAY:
1067 eclass = mono_class_from_mono_type (type->data.array->type);
1068 class = mono_array_class_get (eclass, type->data.array->rank);
1070 case MONO_TYPE_SZARRAY:
1071 eclass = mono_class_from_mono_type (type->data.type);
1072 class = mono_array_class_get (eclass, 1);
1075 class = mono_class_from_mono_type (type->data.type);
1078 g_warning ("implement me: %08x", type->type);
1079 g_assert_not_reached ();
1082 mono_metadata_free_type (type);
1088 * mono_array_class_get:
1089 * @eclass: element type class
1090 * @rank: the dimension of the array class
1092 * Returns: a class object describing the array with element type @etype and
1096 mono_array_class_get (MonoClass *eclass, guint32 rank)
1100 static MonoClass *parent = NULL;
1104 g_assert (rank <= 255);
1107 parent = mono_defaults.array_class;
1109 if (!parent->inited)
1110 mono_class_init (parent);
1112 image = eclass->image;
1114 g_assert (!eclass->type_token ||
1115 mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
1117 key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
1118 if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
1121 class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
1123 class->image = image;
1124 class->name_space = "System";
1125 class->name = "Array";
1126 class->type_token = 0;
1127 class->flags = TYPE_ATTRIBUTE_CLASS;
1128 class->parent = parent;
1129 class->instance_size = mono_class_instance_size (class->parent);
1130 class->class_size = 0;
1131 class->vtable_size = parent->vtable_size;
1132 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
1133 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
1136 class->element_class = eclass;
1138 class->byval_arg.type = MONO_TYPE_ARRAY;
1139 /* FIXME: complete.... */
1141 class->byval_arg.type = MONO_TYPE_SZARRAY;
1142 class->byval_arg.data.type = &eclass->byval_arg;
1144 class->this_arg = class->byval_arg;
1145 class->this_arg.byref = 1;
1147 g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
1152 * mono_class_instance_size:
1155 * Returns: the size of an object instance
1158 mono_class_instance_size (MonoClass *klass)
1162 mono_class_init (klass);
1164 return klass->instance_size;
1168 * mono_class_value_size:
1171 * This function is used for value types, and return the
1172 * space and the alignment to store that kind of value object.
1174 * Returns: the size of a value of kind @klass
1177 mono_class_value_size (MonoClass *klass, guint32 *align)
1181 /* fixme: check disable, because we still have external revereces to
1182 * mscorlib and Dummy Objects
1184 /*g_assert (klass->valuetype);*/
1186 size = mono_class_instance_size (klass) - sizeof (MonoObject);
1189 *align = klass->min_align;
1195 * mono_class_data_size:
1198 * Returns: the size of the static class data
1201 mono_class_data_size (MonoClass *klass)
1205 mono_class_init (klass);
1207 return klass->class_size;
1211 * Auxiliary routine to mono_class_get_field
1213 * Takes a field index instead of a field token.
1215 static MonoClassField *
1216 mono_class_get_field_idx (MonoClass *class, int idx)
1218 if (class->field.count){
1219 if ((idx >= class->field.first) && (idx < class->field.last)){
1220 return &class->fields [idx - class->field.first];
1227 return mono_class_get_field_idx (class->parent, idx);
1231 * mono_class_get_field:
1232 * @class: the class to lookup the field.
1233 * @field_token: the field token
1235 * Returns: A MonoClassField representing the type and offset of
1236 * the field, or a NULL value if the field does not belong to this
1240 mono_class_get_field (MonoClass *class, guint32 field_token)
1242 int idx = mono_metadata_token_index (field_token);
1244 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
1246 return mono_class_get_field_idx (class, idx - 1);
1250 mono_class_get_field_from_name (MonoClass *klass, const char *name)
1254 MonoTableInfo *t = &klass->image->tables [MONO_TABLE_FIELD];
1256 for (i = 0; i < klass->field.count; ++i) {
1257 token = mono_metadata_decode_row_col (t, klass->field.first + i, MONO_FIELD_NAME);
1258 if (strcmp (name, mono_metadata_string_heap (klass->image, token)) == 0)
1259 return &klass->fields [i];
1266 * @image: the image where the class resides
1267 * @type_token: the token for the class
1268 * @at: an optional pointer to return the array element type
1270 * Returns: the MonoClass that represents @type_token in @image
1273 mono_class_get (MonoImage *image, guint32 type_token)
1277 switch (type_token & 0xff000000){
1278 case MONO_TOKEN_TYPE_DEF:
1279 class = mono_class_create_from_typedef (image, type_token);
1281 case MONO_TOKEN_TYPE_REF:
1282 return mono_class_create_from_typeref (image, type_token);
1283 case MONO_TOKEN_TYPE_SPEC:
1284 class = mono_class_create_from_typespec (image, type_token);
1287 g_warning ("unknown token type %x", type_token & 0xff000000);
1288 g_assert_not_reached ();
1295 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
1297 GHashTable *nspace_table;
1300 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
1303 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
1306 /*g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);*/
1310 token = MONO_TOKEN_TYPE_DEF | token;
1312 return mono_class_get (image, token);
1316 * mono_array_element_size:
1317 * @ac: pointer to a #MonoArrayClass
1319 * Returns: the size of single array element.
1322 mono_array_element_size (MonoClass *ac)
1324 if (ac->element_class->valuetype)
1325 return mono_class_instance_size (ac->element_class) - sizeof (MonoObject);
1327 return sizeof (gpointer);
1331 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
1333 switch (token & 0xff000000) {
1334 case MONO_TOKEN_TYPE_DEF:
1335 case MONO_TOKEN_TYPE_REF: {
1338 *handle_class = mono_defaults.typehandle_class;
1339 class = mono_class_get (image, token);
1340 mono_class_init (class);
1341 /* We return a MonoType* as handle */
1342 return &class->byval_arg;
1344 case MONO_TOKEN_TYPE_SPEC: {
1347 *handle_class = mono_defaults.typehandle_class;
1348 class = mono_class_create_from_typespec (image, token);
1349 mono_class_init (class);
1350 return &class->byval_arg;
1352 case MONO_TOKEN_FIELD_DEF: {
1354 guint32 type = mono_metadata_typedef_from_field (image, mono_metadata_token_index (token));
1355 class = mono_class_get (image, MONO_TOKEN_TYPE_DEF | type);
1356 mono_class_init (class);
1358 *handle_class = mono_class_from_name (mono_defaults.corlib, "System", "RuntimeFieldHandle");
1359 return mono_class_get_field (class, token);
1361 case MONO_TOKEN_METHOD_DEF:
1362 case MONO_TOKEN_MEMBER_REF:
1364 g_warning ("Unknown token 0x%08x in ldtoken", token);