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/cli/class.h>
25 #include <mono/cli/types.h>
26 #include <mono/cli/object.h>
28 #define CSIZE(x) (sizeof (x) / 4)
31 * mono_field_type_size:
32 * @t: the type to return the size of
34 * Returns: the number of bytes required to hold an instance of this
38 mono_field_type_size (MonoFieldType *ft)
40 MonoType *t = ft->type;
43 case ELEMENT_TYPE_BOOLEAN:
44 return sizeof (m_boolean);
46 case ELEMENT_TYPE_CHAR:
47 return sizeof (m_char);
73 case ELEMENT_TYPE_STRING:
74 return sizeof (m_string);
76 case ELEMENT_TYPE_OBJECT:
77 return sizeof (m_object);
79 case ELEMENT_TYPE_VALUETYPE:
80 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_VALUETYPE");
82 case ELEMENT_TYPE_CLASS:
83 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_CLASS");
86 case ELEMENT_TYPE_SZARRAY:
87 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_SZARRAY");
90 case ELEMENT_TYPE_PTR:
91 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_PTR");
94 case ELEMENT_TYPE_FNPTR:
95 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_FNPTR");
98 case ELEMENT_TYPE_ARRAY:
99 g_error ("FIXME: Add computation of size for ELEMENT_TYPE_ARRAY");
102 g_error ("type 0x%02x unknown", t->type);
108 * class_compute_field_layout:
109 * @m: pointer to the metadata.
110 * @class: The class to initialize
112 * Initializes the class->fields.
114 * Currently we only support AUTO_LAYOUT, and do not even try to do
115 * a good job at it. This is temporary to get the code for Paolo.
118 class_compute_field_layout (metadata_t *m, MonoClass *class)
120 const int top = class->field.count;
121 guint32 layout = class->flags & TYPE_ATTRIBUTE_LAYOUT_MASK;
122 metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
126 * Fetch all the field information.
128 for (i = 0; i < top; i++){
131 int idx = class->field.first + i;
133 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
134 sig = mono_metadata_blob_heap (m, cols [2]);
135 mono_metadata_decode_value (sig, &sig);
137 /* FIELD signature == 0x06 */
138 g_assert (*sig == 0x06);
140 class->fields [i].type = mono_metadata_parse_field_type (
142 class->fields [i].flags = cols [0];
146 * Compute field layout and total size.
149 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
150 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
151 for (i = 0; i < top; i++){
154 size = mono_field_type_size (class->fields [i].type);
156 if (class->fields [i].flags & FIELD_ATTRIBUTE_STATIC) {
157 class->fields [i].offset = class->class_size;
158 class->class_size += size;
160 class->fields [i].offset = class->instance_size;
161 class->instance_size += size;
165 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
166 g_error ("TODO: Explicit layout not supported yet");
171 * @image: context where the image is created
172 * @tidx: index of the type to create
175 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
177 metadata_t *m = &image->metadata;
178 metadata_tableinfo_t *tt = &m->tables [META_TABLE_TYPEDEF];
179 MonoClass stack_class;
180 MonoClass *class = &stack_class;
181 guint32 cols [6], parent_token;
182 guint tidx = type_token & 0xffffff;
185 mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
186 name = mono_metadata_string_heap (m, cols[1]);
187 /*g_print ("Init class %s\n", name);*/
190 * If root of the hierarchy
193 class->instance_size = sizeof (MonoObject);
194 class->parent = NULL;
196 parent_token = mono_metadata_token_from_dor (cols [3]);
197 class->parent = mono_class_get (image, parent_token);
198 class->instance_size = class->parent->instance_size;
201 class->image = image;
202 class->type_token = tidx;
203 class->flags = cols [0];
204 class->class_size = sizeof (MonoClass);
207 * Compute the field and method lists
209 class->field.first = cols [4] - 1;
210 class->method.first = cols [5] - 1;
212 if (tt->rows > tidx + 1){
213 guint32 cols_next [6];
215 mono_metadata_decode_row (tt, tidx + 1, cols_next, CSIZE (cols_next));
216 class->field.last = cols_next [4] - 1;
217 class->method.last = cols_next [5] - 1;
219 class->field.last = m->tables [META_TABLE_FIELD].rows;
220 class->method.last = m->tables [META_TABLE_METHOD].rows;
223 if (cols [4] && cols [4] <= m->tables [META_TABLE_FIELD].rows)
224 class->field.count = class->field.last - class->field.first;
226 class->field.count = 0;
228 if (cols [5] <= m->tables [META_TABLE_METHOD].rows)
229 class->method.count = class->method.last - class->method.first;
231 class->method.count = 0;
234 * Computes the size used by the fields, and their locations
236 if (class->field.count > 0){
237 class->fields = g_new (MonoClassField, class->field.count);
238 class_compute_field_layout (m, class);
241 class = g_malloc0 (class->class_size);
242 *class = stack_class;
247 * Auxiliary routine to mono_class_get_field
249 * Takes a field index instead of a field token.
251 static MonoClassField *
252 mono_class_get_field_idx (MonoClass *class, int idx)
254 if (class->field.count){
255 if ((idx >= class->field.first) && (idx < class->field.last)){
256 return &class->fields [idx - class->field.first];
263 return mono_class_get_field_idx (class->parent, idx);
267 * mono_class_get_field:
268 * @class: the class to lookup the field.
269 * @field_token: the field token
271 * Returns: A MonoClassField representing the type and offset of
272 * the field, or a NULL value if the field does not belong to this
276 mono_class_get_field (MonoClass *class, guint32 field_token)
278 int idx = mono_metadata_token_index (field_token);
280 if (mono_metadata_token_code (field_token) == TOKEN_TYPE_MEMBER_REF)
281 g_error ("Unsupported Field Token is a MemberRef, implement me");
283 g_assert (mono_metadata_token_code (field_token) == TOKEN_TYPE_FIELD_DEF);
285 return mono_class_get_field_idx (class, idx - 1);
289 typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
292 metadata_t *m = &image->metadata;
293 metadata_tableinfo_t *t = &m->tables[META_TABLE_TYPEREF];
295 const char *name, *nspace;
297 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
298 g_assert ((cols [0] & 0x3) == 2);
300 name = mono_metadata_string_heap (m, cols [1]);
301 nspace = mono_metadata_string_heap (m, cols [2]);
302 /* load referenced assembly */
303 image = image->references [idx-1]->image;
304 m = &image->metadata;
305 t = &m->tables [META_TABLE_TYPEDEF];
306 /* dumb search for now */
307 for (i=0; i < t->rows; ++i) {
308 mono_metadata_decode_row (t, i, cols, 6);
309 if (strcmp (name, mono_metadata_string_heap (m, cols [1])) == 0
310 && strcmp (nspace, mono_metadata_string_heap (m, cols [2])) == 0) {
316 g_assert_not_reached ();
322 * @image: the image where the class resides
323 * @type_token: the token for the class
325 * Returns: the MonoClass that represents @type_token in @image
328 mono_class_get (MonoImage *image, guint32 type_token)
332 if ((type_token & 0xff000000) == TOKEN_TYPE_TYPE_DEF
333 && (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
336 switch (type_token & 0xff000000){
337 case TOKEN_TYPE_TYPE_DEF:
338 class = mono_class_create_from_typedef (image, type_token);
341 case TOKEN_TYPE_TYPE_REF: {
342 typedef_from_typeref (image, type_token, &image, &type_token);
343 class = mono_class_create_from_typedef (image, type_token);
346 case TOKEN_TYPE_TYPE_SPEC:
347 g_error ("Can not handle class creation of TypeSpecs yet");
350 g_assert_not_reached ();
353 g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);