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.
19 #include <mono/metadata/image.h>
20 #include <mono/metadata/cil-coff.h>
21 #include <mono/metadata/metadata.h>
22 #include <mono/metadata/tabledefs.h>
23 #include <mono/metadata/tokentype.h>
24 #include <mono/metadata/class.h>
25 #include <mono/metadata/object.h>
27 #define CSIZE(x) (sizeof (x) / 4)
29 gpointer arch_compile_method (MonoMethod *method);
32 mono_class_create_from_typeref (MonoImage *image, guint32 type_token)
34 guint32 cols [MONO_TYPEREF_SIZE];
35 MonoTableInfo *t = &image->tables [MONO_TABLE_TYPEREF];
37 const char *name, *nspace;
40 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, MONO_TYPEREF_SIZE);
41 g_assert ((cols [MONO_TYPEREF_SCOPE] & 0x3) == 2);
42 idx = cols [MONO_TYPEREF_SCOPE] >> 2;
44 if (!image->references || !image->references [idx-1]) {
46 * detected a reference to mscorlib, we simply return a reference to a dummy
47 * until we have a better solution.
49 fprintf(stderr, "Sending dummy where %s expected\n", mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]));
50 res = mono_class_from_name (image, "System", "MonoDummy");
51 /* prevent method loading */
53 /* some storage if the type is used - very ugly hack */
54 res->instance_size = 2*sizeof (gpointer);
58 name = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAME]);
59 nspace = mono_metadata_string_heap (image, cols [MONO_TYPEREF_NAMESPACE]);
61 /* load referenced assembly */
62 image = image->references [idx-1]->image;
64 return mono_class_from_name (image, nspace, name);
68 * class_compute_field_layout:
69 * @m: pointer to the metadata.
70 * @class: The class to initialize
72 * Initializes the class->fields.
74 * Currently we only support AUTO_LAYOUT, and do not even try to do
75 * a good job at it. This is temporary to get the code for Paolo.
78 class_compute_field_layout (MonoClass *class)
80 MonoImage *m = class->image;
81 const int top = class->field.count;
82 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
83 MonoTableInfo *t = &m->tables [MONO_TABLE_FIELD];
87 * Fetch all the field information.
89 for (i = 0; i < top; i++){
92 int idx = class->field.first + i;
94 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
95 sig = mono_metadata_blob_heap (m, cols [2]);
96 mono_metadata_decode_value (sig, &sig);
97 /* FIELD signature == 0x06 */
98 g_assert (*sig == 0x06);
99 class->fields [i].type = mono_metadata_parse_field_type (
100 m, cols [MONO_FIELD_FLAGS], sig + 1, &sig);
103 * Compute field layout and total size.
106 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
107 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
108 for (i = 0; i < top; i++){
111 size = mono_type_size (class->fields [i].type, &align);
112 if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
113 class->fields [i].offset = class->class_size;
114 class->class_size += (class->class_size % align);
115 class->class_size += size;
117 class->fields [i].offset = class->instance_size;
118 class->instance_size += (class->instance_size % align);
119 class->instance_size += size;
123 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
124 for (i = 0; i < top; i++){
127 int idx = class->field.first + i;
129 t = &m->tables [MONO_TABLE_FIELDLAYOUT];
131 for (j = 0; j < t->rows; j++) {
133 mono_metadata_decode_row (t, j, cols, CSIZE (cols));
134 if (cols [1] == idx) {
135 g_warning ("TODO: Explicit layout not supported yet");
139 size = mono_type_size (class->fields [i].type, &align);
140 if (class->fields [i].type->attrs & FIELD_ATTRIBUTE_STATIC) {
141 class->fields [i].offset = class->class_size;
142 class->class_size += (class->class_size % align);
143 class->class_size += size;
145 class->fields [i].offset = class->instance_size;
146 class->instance_size += (class->instance_size % align);
147 class->instance_size += size;
155 mono_class_metadata_init (MonoClass *class)
158 MonoMethod **tmp_vtable, **vtable = (MonoMethod **)class->vtable;
159 int i, max_iid, cur_slot = 0;
163 if (class->metadata_inited)
167 if (!class->parent->metadata_inited)
168 mono_class_metadata_init (class->parent);
169 class->instance_size += class->parent->instance_size;
170 class->class_size += class->parent->class_size;
171 cur_slot = class->parent->vtable_size;
174 class->metadata_inited = 1;
177 * Computes the size used by the fields, and their locations
179 if (class->field.count > 0){
180 class->fields = g_new (MonoClassField, class->field.count);
181 class_compute_field_layout (class);
184 if (class->class_size)
185 class->data = g_malloc0 (class->class_size);
187 /* initialize mothod pointers */
188 class->methods = g_new (MonoMethod*, class->method.count);
189 for (i = 0; i < class->method.count; ++i)
190 class->methods [i] = mono_get_method (class->image,
191 MONO_TOKEN_METHOD_DEF | (i + class->method.first + 1), class);
193 if (class->flags & TYPE_ATTRIBUTE_INTERFACE) {
194 for (i = 0; i < class->method.count; ++i)
195 class->methods [i]->slot = i;
199 //printf ("METAINIT %s.%s\n", class->name_space, class->name);
201 /* compute maximum number of slots and maximum interface id */
203 for (k = class; k ; k = k->parent) {
204 for (i = 0; i < k->interface_count; i++) {
205 ic = k->interfaces [i];
207 if (!ic->metadata_inited)
208 mono_class_metadata_init (ic);
210 if (max_iid < ic->interface_id)
211 max_iid = ic->interface_id;
215 /* compute vtable offset for interfaces */
216 class->interface_offsets = g_malloc (sizeof (gpointer) * (max_iid + 1));
218 for (i = 0; i <= max_iid; i++)
219 class->interface_offsets [i] = NULL;
221 for (i = 0; i < class->interface_count; i++) {
222 ic = class->interfaces [i];
223 class->interface_offsets [ic->interface_id] = &class->vtable [cur_slot];
224 cur_slot += ic->method.count;
227 for (k = class->parent; k ; k = k->parent) {
228 for (i = 0; i < k->interface_count; i++) {
229 ic = k->interfaces [i];
230 if (class->interface_offsets [ic->interface_id] == NULL)
231 class->interface_offsets [ic->interface_id] =
232 &class->vtable [(k->interface_offsets [ic->interface_id] - (gpointer)k->vtable)>>2];
236 if (class->parent && class->parent->vtable_size)
237 memcpy (class->vtable, class->parent->vtable, sizeof (gpointer) * class->parent->vtable_size);
239 tmp_vtable = alloca (class->vtable_size * sizeof (gpointer));
240 memset (tmp_vtable, 0, class->vtable_size * sizeof (gpointer));
242 for (k = class; k ; k = k->parent) {
243 for (i = 0; i < k->interface_count; i++) {
245 ic = k->interfaces [i];
247 io = (class->interface_offsets [ic->interface_id] - (gpointer)k->vtable)>>2;
250 for (l = 0; l < ic->method.count; l++) {
251 MonoMethod *im = ic->methods [l];
252 for (j = 0; j < class->method.count; ++j) {
253 MonoMethod *cm = class->methods [j];
254 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
255 !(cm->flags & METHOD_ATTRIBUTE_PUBLIC) ||
256 !(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT))
258 if (!strcmp(cm->name, im->name) &&
259 mono_metadata_signature_equal (cm->signature, im->signature)) {
260 tmp_vtable [io + l] = cm;
265 /* already implemented */
266 if (io >= k->vtable_size)
270 for (l = 0; l < ic->method.count; l++) {
271 MonoMethod *im = ic->methods [l];
274 if (tmp_vtable [io + l] || vtable [io + l])
277 for (k1 = class; k1; k1 = k1->parent) {
278 for (j = 0; j < k1->method.count; ++j) {
279 MonoMethod *cm = k1->methods [j];
281 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
282 !(cm->flags & METHOD_ATTRIBUTE_PUBLIC))
285 if (!strcmp(cm->name, im->name) &&
286 mono_metadata_signature_equal (cm->signature, im->signature)) {
287 tmp_vtable [io + l] = cm;
292 if (tmp_vtable [io + l])
297 for (l = 0; l < ic->method.count; l++) {
298 MonoMethod *im = ic->methods [l];
300 if (ic->name_space && ic->name_space [0])
301 qname = g_strconcat (ic->name_space, ".", ic->name, ".", im->name, NULL);
303 qname = g_strconcat (ic->name, ".", im->name, NULL);
305 for (j = 0; j < class->method.count; ++j) {
306 MonoMethod *cm = class->methods [j];
308 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL))
311 if (!strcmp (cm->name, qname) &&
312 mono_metadata_signature_equal (cm->signature, im->signature)) {
313 tmp_vtable [io + l] = cm;
321 if (!(class->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
322 for (l = 0; l < ic->method.count; l++) {
323 MonoMethod *im = ic->methods [l];
324 if (!(tmp_vtable [io + l] || vtable [io + l])) {
325 printf ("no implementation for interface method %s.%s::%s in class %s.%s\n",
326 ic->name_space, ic->name, im->name, class->name_space, class->name);
328 for (j = 0; j < class->method.count; ++j) {
329 MonoMethod *cm = class->methods [j];
331 printf ("METHOD %s\n", cm->name);
333 g_assert_not_reached ();
338 for (l = 0; l < ic->method.count; l++) {
339 MonoMethod *im = tmp_vtable [io + l];
341 if (im && !(im->flags & METHOD_ATTRIBUTE_ABSTRACT)) {
343 //printf (" ASLOT%d %s.%s:%s\n", io + l, ic->name_space, ic->name, im->name);
344 vtable [io + l] = arch_compile_method (im);
350 for (i = 0; i < class->method.count; ++i) {
353 cm = class->methods [i];
355 if (!(cm->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
359 if (!(cm->flags & METHOD_ATTRIBUTE_NEW_SLOT)) {
360 for (k = class->parent; k ; k = k->parent) {
362 for (j = 0; j < k->method.count; ++j) {
363 MonoMethod *m1 = k->methods [j];
364 if (!(m1->flags & METHOD_ATTRIBUTE_VIRTUAL))
366 if (!strcmp(cm->name, m1->name) &&
367 mono_metadata_signature_equal (cm->signature, m1->signature)) {
368 cm->slot = k->methods [j]->slot;
378 cm->slot = cur_slot++;
380 if (!(cm->flags & METHOD_ATTRIBUTE_ABSTRACT))
381 vtable [cm->slot] = arch_compile_method (cm);
385 for (i = 0; i < class->vtable_size; ++i) {
390 printf (" METH%d %p %s %d\n", i, cm, cm->name, cm->slot);
395 //printf ("METAEND %s.%s\n", class->name_space, class->name);
399 * Compute a relative numbering of the class hierarchy as described in
400 * "Java for Large-Scale Scientific Computations?"
403 mono_compute_relative_numbering (MonoClass *class, int *c)
411 for (s = class->subclasses; s; s = s->next)
412 mono_compute_relative_numbering ((MonoClass *)s->data, c);
414 class->diffval = *c - class->baseval;
418 * @image: context where the image is created
419 * @type_token: typedef token
422 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
424 MonoTableInfo *tt = &image->tables [MONO_TABLE_TYPEDEF];
425 MonoClass *class, *parent = NULL;
426 guint32 cols [MONO_TYPEDEF_SIZE];
427 guint32 cols_next [MONO_TYPEDEF_SIZE];
428 guint tidx = mono_metadata_token_index (type_token);
429 const char *name, *nspace;
430 guint vtsize = 0, icount = 0;
431 static guint interface_id = 0;
432 MonoClass **interfaces;
435 g_assert (mono_metadata_token_table (type_token) == MONO_TABLE_TYPEDEF);
437 mono_metadata_decode_row (tt, tidx - 1, cols, CSIZE (cols));
439 if (tt->rows > tidx) {
440 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
441 vtsize += cols_next [MONO_TYPEDEF_METHOD_LIST] - cols [MONO_TYPEDEF_METHOD_LIST];
443 vtsize += image->tables [MONO_TABLE_METHOD].rows - cols [MONO_TYPEDEF_METHOD_LIST] + 1;
446 name = mono_metadata_string_heap (image, cols[1]);
447 nspace = mono_metadata_string_heap (image, cols[2]);
449 if (!(!strcmp (nspace, "System") && !strcmp (name, "Object")) &&
450 !(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
451 parent = mono_class_get (image, mono_metadata_token_from_dor (cols [3]));
453 interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &icount);
455 for (i = 0; i < icount; i++)
456 vtsize += interfaces [i]->method.count;
459 vtsize += parent->vtable_size;
461 if (cols [0] & TYPE_ATTRIBUTE_INTERFACE)
464 class = g_malloc0 (sizeof (MonoClass) + vtsize * sizeof (gpointer));
466 class->parent = parent;
467 class->interfaces = interfaces;
468 class->interface_count = icount;
469 class->vtable_size = vtsize;
471 class->this_arg.byref = 1;
472 class->this_arg.data.klass = class;
473 class->this_arg.type = MONO_TYPE_CLASS;
474 class->byval_arg.data.klass = class;
475 class->byval_arg.type = MONO_TYPE_CLASS;
478 class->name_space = nspace;
480 class->image = image;
481 class->type_token = type_token;
482 class->flags = cols [0];
484 /*g_print ("Init class %s\n", name);*/
486 /* if root of the hierarchy */
487 if (!strcmp (nspace, "System") && !strcmp (name, "Object")) {
488 class->parent = NULL;
489 class->instance_size = sizeof (MonoObject);
490 } else if (!(cols [0] & TYPE_ATTRIBUTE_INTERFACE)) {
492 class->parent = mono_class_get (image, mono_metadata_token_from_dor (cols [3]));
493 class->valuetype = class->parent->valuetype;
494 class->enumtype = class->parent->enumtype;
495 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
496 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
499 if (!strcmp (nspace, "System")) {
500 if (!strcmp (name, "ValueType")) {
501 class->valuetype = 1;
502 } else if (!strcmp (name, "Enum")) {
503 class->valuetype = 1;
508 if (class->valuetype) {
509 int t = MONO_TYPE_VALUETYPE;
510 if (!strcmp (nspace, "System")) {
513 if (!strcmp (name, "Boolean")) {
514 t = MONO_TYPE_BOOLEAN;
515 } else if (!strcmp(name, "Byte")) {
520 if (!strcmp (name, "Char")) {
525 if (!strcmp (name, "Double")) {
530 if (!strcmp (name, "Int32")) {
532 } else if (!strcmp(name, "Int16")) {
534 } else if (!strcmp(name, "Int64")) {
536 } else if (!strcmp(name, "IntPtr")) {
541 if (!strcmp (name, "Object")) {
542 t = MONO_TYPE_OBJECT;
546 if (!strcmp (name, "Single")) {
548 } else if (!strcmp(name, "String")) {
549 t = MONO_TYPE_STRING;
550 } else if (!strcmp(name, "SByte")) {
555 if (!strcmp (name, "UInt32")) {
557 } else if (!strcmp(name, "UInt16")) {
559 } else if (!strcmp(name, "UInt64")) {
561 } else if (!strcmp(name, "UIntPtr")) {
566 if (!strcmp (name, "Void")) {
574 class->this_arg.type = class->byval_arg.type = t;
578 * Compute the field and method lists
580 class->field.first = cols [MONO_TYPEDEF_FIELD_LIST] - 1;
581 class->method.first = cols [MONO_TYPEDEF_METHOD_LIST] - 1;
583 if (tt->rows > tidx){
584 mono_metadata_decode_row (tt, tidx, cols_next, CSIZE (cols_next));
585 class->field.last = cols_next [MONO_TYPEDEF_FIELD_LIST] - 1;
586 class->method.last = cols_next [MONO_TYPEDEF_METHOD_LIST] - 1;
588 class->field.last = image->tables [MONO_TABLE_FIELD].rows;
589 class->method.last = image->tables [MONO_TABLE_METHOD].rows;
592 if (cols [MONO_TYPEDEF_FIELD_LIST] &&
593 cols [MONO_TYPEDEF_FIELD_LIST] <= image->tables [MONO_TABLE_FIELD].rows)
594 class->field.count = class->field.last - class->field.first;
596 class->field.count = 0;
598 if (cols [MONO_TYPEDEF_METHOD_LIST] <= image->tables [MONO_TABLE_METHOD].rows)
599 class->method.count = class->method.last - class->method.first;
601 class->method.count = 0;
603 /* reserve space to store vector pointer in arrays */
604 if (!strcmp (nspace, "System") && !strcmp (name, "Array")) {
605 class->instance_size += 2 * sizeof (gpointer);
606 g_assert (class->field.count == 0);
609 if (class->flags & TYPE_ATTRIBUTE_INTERFACE)
610 class->interface_id = interface_id++;
612 //class->interfaces = mono_metadata_interfaces_from_typedef (image, type_token, &class->interface_count);
618 mono_class_from_mono_type (MonoType *type)
620 switch (type->type) {
621 case MONO_TYPE_OBJECT:
622 return mono_defaults.object_class;
624 return mono_defaults.void_class;
625 case MONO_TYPE_BOOLEAN:
626 return mono_defaults.boolean_class;
628 return mono_defaults.char_class;
630 return mono_defaults.byte_class;
632 return mono_defaults.sbyte_class;
634 return mono_defaults.int16_class;
636 return mono_defaults.uint16_class;
638 return mono_defaults.int32_class;
640 return mono_defaults.uint32_class;
642 return mono_defaults.int_class;
644 return mono_defaults.uint_class;
646 return mono_defaults.int64_class;
648 return mono_defaults.uint64_class;
650 return mono_defaults.single_class;
652 return mono_defaults.double_class;
653 case MONO_TYPE_STRING:
654 return mono_defaults.string_class;
655 case MONO_TYPE_ARRAY:
656 return mono_defaults.array_class;
657 case MONO_TYPE_SZARRAY:
659 /* Not really sure about these. */
660 return mono_class_from_mono_type (type->data.type);
661 case MONO_TYPE_CLASS:
662 case MONO_TYPE_VALUETYPE:
663 return type->data.klass;
665 g_warning ("implement me %02x\n", type->type);
666 g_assert_not_reached ();
673 * @image: context where the image is created
674 * @type_spec: typespec token
675 * @at: an optional pointer to return the array type
678 mono_class_create_from_typespec (MonoImage *image, guint32 type_spec)
680 guint32 idx = mono_metadata_token_index (type_spec);
682 guint32 cols [MONO_TYPESPEC_SIZE];
686 MonoClass *class, *eclass;
688 t = &image->tables [MONO_TABLE_TYPESPEC];
690 mono_metadata_decode_row (t, idx-1, cols, MONO_TYPESPEC_SIZE);
691 ptr = mono_metadata_blob_heap (image, cols [MONO_TYPESPEC_SIGNATURE]);
692 len = mono_metadata_decode_value (ptr, &ptr);
693 type = mono_metadata_parse_type (image, MONO_PARSE_TYPE, 0, ptr, &ptr);
695 switch (type->type) {
696 case MONO_TYPE_ARRAY:
697 eclass = mono_class_from_mono_type (type->data.array->type);
698 class = mono_array_class_get (eclass, type->data.array->rank);
700 case MONO_TYPE_SZARRAY:
701 eclass = mono_class_from_mono_type (type->data.type);
702 class = mono_array_class_get (eclass, 1);
705 g_warning ("implement me: %08x", type->type);
706 g_assert_not_reached ();
709 mono_metadata_free_type (type);
715 * mono_array_class_get:
716 * @eclass: element type class
717 * @rank: the dimension of the array class
719 * Returns: a class object describing the array with element type @etype and
723 mono_array_class_get (MonoClass *eclass, guint32 rank)
727 static MonoClass *parent = NULL;
731 g_assert (rank <= 255);
734 parent = mono_defaults.array_class;
736 if (!parent->metadata_inited)
737 mono_class_metadata_init (parent);
739 image = eclass->image;
741 g_assert (!eclass->type_token ||
742 mono_metadata_token_table (eclass->type_token) == MONO_TABLE_TYPEDEF);
744 key = ((rank & 0xff) << 24) | (eclass->type_token & 0xffffff);
745 if ((class = g_hash_table_lookup (image->array_cache, GUINT_TO_POINTER (key))))
748 class = g_malloc0 (sizeof (MonoClass) + parent->vtable_size * sizeof (gpointer));
750 class->image = image;
751 class->name_space = "System";
752 class->name = "Array";
753 class->type_token = 0;
754 class->flags = TYPE_ATTRIBUTE_CLASS;
755 class->parent = parent;
756 class->instance_size = mono_class_instance_size (class->parent);
757 class->class_size = 0;
758 class->vtable_size = parent->vtable_size;
759 class->parent->subclasses = g_list_prepend (class->parent->subclasses, class);
760 mono_compute_relative_numbering (mono_defaults.object_class, &rnum);
763 class->element_class = eclass;
765 g_hash_table_insert (image->array_cache, GUINT_TO_POINTER (key), class);
770 * mono_class_instance_size:
773 * Returns: the size of an object instance
776 mono_class_instance_size (MonoClass *klass)
779 if (!klass->metadata_inited)
780 mono_class_metadata_init (klass);
782 return klass->instance_size;
786 * mono_class_value_size:
789 * This function is used for value types, and return the
790 * space and the alignment to store that kind of value object.
792 * Returns: the size of a value of kind @klass
795 mono_class_value_size (MonoClass *klass, guint32 *align)
799 /* fixme: check disable, because we still have external revereces to
800 * mscorlib and Dummy Objects
802 /*g_assert (klass->valuetype);*/
804 size = mono_class_instance_size (klass) - sizeof (MonoObject);
817 * mono_class_data_size:
820 * Returns: the size of the static class data
823 mono_class_data_size (MonoClass *klass)
826 if (!klass->metadata_inited)
827 mono_class_metadata_init (klass);
829 return klass->class_size;
833 * Auxiliary routine to mono_class_get_field
835 * Takes a field index instead of a field token.
837 static MonoClassField *
838 mono_class_get_field_idx (MonoClass *class, int idx)
840 if (class->field.count){
841 if ((idx >= class->field.first) && (idx < class->field.last)){
842 return &class->fields [idx - class->field.first];
849 return mono_class_get_field_idx (class->parent, idx);
853 * mono_class_get_field:
854 * @class: the class to lookup the field.
855 * @field_token: the field token
857 * Returns: A MonoClassField representing the type and offset of
858 * the field, or a NULL value if the field does not belong to this
862 mono_class_get_field (MonoClass *class, guint32 field_token)
864 int idx = mono_metadata_token_index (field_token);
866 if (mono_metadata_token_code (field_token) == MONO_TOKEN_MEMBER_REF)
867 g_error ("Unsupported Field Token is a MemberRef, implement me");
869 g_assert (mono_metadata_token_code (field_token) == MONO_TOKEN_FIELD_DEF);
871 return mono_class_get_field_idx (class, idx - 1);
875 mono_class_get_field_from_name (MonoClass *klass, const char *name)
879 MonoTableInfo *t = &klass->image->tables [MONO_TABLE_FIELD];
881 for (i = 0; i < klass->field.count; ++i) {
882 token = mono_metadata_decode_row_col (t, klass->field.first + i, MONO_FIELD_NAME);
883 if (strcmp (name, mono_metadata_string_heap (klass->image, token)) == 0)
884 return &klass->fields [i];
891 * @image: the image where the class resides
892 * @type_token: the token for the class
893 * @at: an optional pointer to return the array element type
895 * Returns: the MonoClass that represents @type_token in @image
898 mono_class_get (MonoImage *image, guint32 type_token)
902 switch (type_token & 0xff000000){
903 case MONO_TOKEN_TYPE_DEF:
904 if ((class = g_hash_table_lookup (image->class_cache,
905 GUINT_TO_POINTER (type_token))))
907 class = mono_class_create_from_typedef (image, type_token);
909 case MONO_TOKEN_TYPE_REF:
910 return mono_class_create_from_typeref (image, type_token);
911 case MONO_TOKEN_TYPE_SPEC:
912 if ((class = g_hash_table_lookup (image->class_cache,
913 GUINT_TO_POINTER (type_token))))
916 class = mono_class_create_from_typespec (image, type_token);
919 g_assert_not_reached ();
922 g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);
928 mono_class_from_name (MonoImage *image, const char* name_space, const char *name)
930 GHashTable *nspace_table;
933 nspace_table = g_hash_table_lookup (image->name_cache, name_space);
936 token = GPOINTER_TO_UINT (g_hash_table_lookup (nspace_table, name));
939 g_warning ("token not found for %s.%s in image %s", name_space, name, image->name);
943 token = MONO_TOKEN_TYPE_DEF | token;
945 return mono_class_get (image, token);
949 * mono_array_element_size:
950 * @ac: pointer to a #MonoArrayClass
952 * Returns: the size of single array element.
955 mono_array_element_size (MonoClass *ac)
959 esize = mono_class_instance_size (ac->element_class);
961 if (ac->element_class->valuetype)
962 esize -= sizeof (MonoObject);
968 mono_ldtoken (MonoImage *image, guint32 token, MonoClass **handle_class)
970 switch (token & 0xff000000) {
971 case MONO_TOKEN_TYPE_DEF:
972 case MONO_TOKEN_TYPE_REF: {
975 *handle_class = mono_defaults.typehandle_class;
976 class = mono_class_get (image, token);
977 /* We return a MonoType* as handle */
978 return &class->byval_arg;
980 case MONO_TOKEN_METHOD_DEF:
981 case MONO_TOKEN_FIELD_DEF:
982 case MONO_TOKEN_MEMBER_REF: