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];
123 int instance_size = sizeof (MonoObject);
127 * Fetch all the field information.
129 for (i = 0; i < top; i++){
132 int idx = class->field.first + i;
134 mono_metadata_decode_row (t, idx, cols, CSIZE (cols));
135 sig = mono_metadata_blob_heap (m, cols [2]);
136 mono_metadata_decode_value (sig, &sig);
138 /* FIELD signature == 0x06 */
139 g_assert (*sig == 0x06);
141 class->fields [i].type = mono_metadata_parse_field_type (
143 class->fields [i].flags = cols [0];
147 * Compute field layout and total size.
150 case TYPE_ATTRIBUTE_AUTO_LAYOUT:
151 for (i = 0; i < top; i++){
154 class->fields [i].offset = instance_size;
156 size = mono_field_type_size (class->fields [i].type);
158 instance_size += size;
162 case TYPE_ATTRIBUTE_SEQUENTIAL_LAYOUT:
163 for (i = 0; i < top; i++){
166 class->fields [i].offset = instance_size;
168 size = mono_field_type_size (class->fields [i].type);
170 instance_size += size;
174 case TYPE_ATTRIBUTE_EXPLICIT_LAYOUT:
175 g_error ("TODO: Explicit layout not supported yet");
180 * @image: context where the image is created
181 * @tidx: index of the type to create
184 mono_class_create_from_typedef (MonoImage *image, guint32 type_token)
186 metadata_t *m = &image->metadata;
187 metadata_tableinfo_t *tt = &m->tables [META_TABLE_TYPEDEF];
189 guint32 cols [6], parent_token;
190 guint tidx = type_token & 0xffffff;
193 mono_metadata_decode_row (tt, tidx-1, cols, CSIZE (cols));
194 name = mono_metadata_string_heap (m, cols[1]);
195 /*g_print ("Init class %s\n", name);*/
197 class = g_new0 (MonoClass, 1);
200 * If root of the hierarchy
203 class->instance_size = sizeof (MonoObject);
204 class->parent = NULL;
206 parent_token = mono_metadata_token_from_dor (cols [3]);
207 class->parent = mono_class_get (image, parent_token);
208 class->instance_size = class->parent->instance_size;
211 class->image = image;
212 class->type_token = tidx;
213 class->flags = cols [0];
216 * Compute the field and method lists
218 class->field.first = cols [4] - 1;
219 class->method.first = cols [5] - 1;
221 if (tt->rows > tidx + 1){
222 guint32 cols_next [6];
224 mono_metadata_decode_row (tt, tidx + 1, cols_next, CSIZE (cols_next));
225 class->field.last = cols_next [4] - 1;
226 class->method.last = cols_next [5] - 1;
228 class->field.last = m->tables [META_TABLE_FIELD].rows;
229 class->method.last = m->tables [META_TABLE_METHOD].rows;
232 if (cols [4] && cols [4] <= m->tables [META_TABLE_FIELD].rows)
233 class->field.count = class->field.last - class->field.first;
235 class->field.count = 0;
237 if (cols [5] <= m->tables [META_TABLE_METHOD].rows)
238 class->method.count = class->method.last - class->method.first;
240 class->method.count = 0;
243 * Computes the size used by the fields, and their locations
245 if (class->field.count > 0){
246 class->fields = g_new (MonoClassField, class->field.count);
247 class_compute_field_layout (m, class);
254 * Auxiliary routine to mono_class_get_field
256 * Takes a field index instead of a field token.
258 static MonoClassField *
259 mono_class_get_field_idx (MonoClass *class, int idx)
261 if (class->field.count){
262 if ((idx >= class->field.first) && (idx < class->field.last)){
263 return &class->fields [idx - class->field.first];
270 return mono_class_get_field_idx (class->parent, idx);
274 * mono_class_get_field:
275 * @class: the class to lookup the field.
276 * @field_token: the field token
278 * Returns: A MonoClassField representing the type and offset of
279 * the field, or a NULL value if the field does not belong to this
283 mono_class_get_field (MonoClass *class, guint32 field_token)
285 int idx = mono_metadata_token_index (field_token);
287 if (mono_metadata_token_code (field_token) == TOKEN_TYPE_MEMBER_REF)
288 g_error ("Unsupported Field Token is a MemberRef, implement me");
290 g_assert (mono_metadata_token_code (field_token) == TOKEN_TYPE_FIELD_DEF);
292 return mono_class_get_field_idx (class, idx - 1);
296 typedef_from_typeref (MonoImage *image, guint32 type_token, MonoImage **rimage, guint32 *index)
299 metadata_t *m = &image->metadata;
300 metadata_tableinfo_t *t = &m->tables[META_TABLE_TYPEREF];
302 const char *name, *nspace;
304 mono_metadata_decode_row (t, (type_token&0xffffff)-1, cols, 3);
305 g_assert ((cols [0] & 0x3) == 2);
307 name = mono_metadata_string_heap (m, cols [1]);
308 nspace = mono_metadata_string_heap (m, cols [2]);
309 /* load referenced assembly */
310 image = image->references [idx-1]->image;
311 m = &image->metadata;
312 t = &m->tables [META_TABLE_TYPEDEF];
313 /* dumb search for now */
314 for (i=0; i < t->rows; ++i) {
315 mono_metadata_decode_row (t, i, cols, 6);
316 if (strcmp (name, mono_metadata_string_heap (m, cols [1])) == 0
317 && strcmp (nspace, mono_metadata_string_heap (m, cols [2])) == 0) {
323 g_assert_not_reached ();
329 * @image: the image where the class resides
330 * @type_token: the token for the class
332 * Returns: the MonoClass that represents @type_token in @image
335 mono_class_get (MonoImage *image, guint32 type_token)
339 if ((type_token & 0xff000000) == TOKEN_TYPE_TYPE_DEF
340 && (class = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
343 switch (type_token & 0xff000000){
344 case TOKEN_TYPE_TYPE_DEF:
345 class = mono_class_create_from_typedef (image, type_token);
348 case TOKEN_TYPE_TYPE_REF: {
349 typedef_from_typeref (image, type_token, &image, &type_token);
350 class = mono_class_create_from_typedef (image, type_token);
353 case TOKEN_TYPE_TYPE_SPEC:
354 g_error ("Can not handle class creation of TypeSpecs yet");
357 g_assert_not_reached ();
360 g_hash_table_insert (image->class_cache, GUINT_TO_POINTER (type_token), class);